API referenceTransactional Email

Transactional Email API

One HTTP call sends a receipt, a password reset, or a booking confirmation from your own verified domain. Everything below works with a live API key. No SDK to install, and nothing to sign in for.

Get an API key

Quickstart

Send mail with one HTTP call. Authenticate with your API key (looks like tk_live_…) and send from a verified sending domain. The examples below use no-reply@send.yourdomain.com as a stand-in for yours. Building with an AI coding assistant? Download the and drop it into your repo. It contains everything your agent needs.

curl
curl -X POST "https://www.zorromail.app/tx/v1/messages" \
  -H "Authorization: Bearer $ZORROMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042-receipt" \
  -d '{
    "from": "no-reply@send.yourdomain.com",
    "fromName": "Acme Support",
    "to": ["customer@example.com"],
    "subject": "Your receipt",
    "html": "<h1>Thanks!</h1><p>Order #1042 confirmed.</p>",
    "text": "Thanks! Order #1042 confirmed."
  }'
node
const res = await fetch('https://www.zorromail.app/tx/v1/messages', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.ZORROMAIL_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': 'order-1042-receipt',
  },
  body: JSON.stringify({
    from: 'no-reply@send.yourdomain.com',
    fromName: 'Acme Support',
    to: ['customer@example.com'],
    subject: 'Your receipt',
    html: '<h1>Thanks!</h1><p>Order #1042 confirmed.</p>',
  }),
});
if (!res.ok) throw new Error(`send failed: ${res.status}`);
const { id, status } = await res.json();
python
import os, requests

res = requests.post(
    "https://www.zorromail.app/tx/v1/messages",
    headers={
        "Authorization": f"Bearer {os.environ['ZORROMAIL_API_KEY']}",
        "Idempotency-Key": "order-1042-receipt",
    },
    json={
        "from": "no-reply@send.yourdomain.com",
        "fromName": "Acme Support",
        "to": ["customer@example.com"],
        "subject": "Your receipt",
        "html": "<h1>Thanks!</h1><p>Order #1042 confirmed.</p>",
    },
    timeout=30,
)
res.raise_for_status()
message = res.json()

Sender name. fromName is what recipients see in their inbox. Leave it out and mail clients fall back to the local part of the address (no-reply), so send a properly capitalized name like Acme Support. You can also write it inline as Acme Support <no-reply@send.yourdomain.com>, or save it once on the sender under Sender emails and every send picks it up automatically.

Request fields

FieldTypeNotes
fromstringRequired. Must be on a verified sending domain, e.g. no-reply@send.yourdomain.com. May carry the sender name inline: Acme Support <no-reply@send.yourdomain.com>
fromNamestringOptional. Sender name shown in the inbox, e.g. Acme Support (max 78 chars). Without it clients display "no-reply"
tostring[]Required. Recipient addresses
subjectstringRequired, max 998 chars
html / textstringAt least one required. Send both for best deliverability
cc, bccstring[]Optional
replyTostringOptional. Where replies land (use a real inbox). Accepts Name <addr@domain>
headersobjectOptional extra headers, e.g. {"X-Order-Id": "123"}
attachmentsarray{filename, contentBase64, contentType}

Optional Idempotency-Key request header: retries with the same key return the original result instead of sending a duplicate. Use it for anything triggered by payments or retried jobs.

Responses & errors

Success is 202 with {"id", "status", "suppressedRecipients?"}. Recipients who previously bounced, complained, or unsubscribed are suppressed automatically. They appear in suppressedRecipients and are never contacted.

StatusMeaningWhat to do
400Validation failedFix the payload; do not retry as-is
401Missing/invalid/revoked API keyCheck the key
422From-domain not verifiedVerify the sending domain first
429Rate limit (100 req/min) or monthly quotaBack off and retry later
502Upstream provider failureRetry with the same Idempotency-Key

Suppression list

Manage suppressed addresses with the same API key:

curl
# list
curl "https://www.zorromail.app/tx/v1/suppressions" -H "Authorization: Bearer $ZORROMAIL_API_KEY"

# add manually
curl -X POST "https://www.zorromail.app/tx/v1/suppressions" \
  -H "Authorization: Bearer $ZORROMAIL_API_KEY" -H "Content-Type: application/json" \
  -d '{"email": "someone@example.com"}'

# remove
curl -X DELETE "https://www.zorromail.app/tx/v1/suppressions/someone@example.com" \
  -H "Authorization: Bearer $ZORROMAIL_API_KEY"

Included automatically

  • Delivery, bounce, complaint, open, and click tracking per message
  • Hard bounces and complaints auto-suppress the recipient
  • One-click List-Unsubscribe header (RFC 8058) on every send
  • Raw copy of every message archived for audit