Send Your First Email

First email in under 3 minutes with a test key — no DNS required

Send your first email in under three minutes. You don't need to configure DNS to get started: a test API key runs the entire pipeline — statuses, timeline, webhooks — without delivering real email. Going live is the last step, not the first.

Step 1: Get a test API key

The onboarding wizard offers one right after signup. You can also create one anytime in the dashboard under Settings → API keys (pick the Test environment), or via API if you already have a key:

curl -X POST https://api.tratto.email/v1/api-keys \
  -H "Authorization: Bearer YOUR_EXISTING_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"quickstart","env":"test","permissions":["emails:send","emails:read"]}'

Test keys start with tratto_test_, live keys with tratto_live_.

The key is shown only once. Treat it like a password, never expose it client-side.

Step 2: Send an email

Any syntactically valid from address works in test mode — no verified domain needed.

cURL

curl -X POST https://api.tratto.email/v1/emails \
  -H "Authorization: Bearer tratto_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "from": "[email protected]",
    "to": "[email protected]",
    "subject": "Hello from Tratto!",
    "text": "If you see this, it works!"
  }'

Node.js

const response = await fetch('https://api.tratto.email/v1/emails', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer tratto_test_...',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    from: '[email protected]',
    to: '[email protected]',
    subject: 'Hello from Tratto!',
    text: 'If you see this, it works!',
  }),
});
const { data } = await response.json();
console.log('Email ID:', data.id); // email_...
console.log('Live mode:', data.livemode); // false

Python

import requests

response = requests.post(
  'https://api.tratto.email/v1/emails',
  headers={
    'Authorization': 'Bearer tratto_test_...',
    'Content-Type': 'application/json',
  },
  json={
    'from': '[email protected]',
    'to': '[email protected]',
    'subject': 'Hello from Tratto!',
    'text': 'If you see this, it works!',
  },
)
data = response.json()['data']
print(data['id'], data['livemode'])  # email_...  False

Response:

{
  "data": {
    "id": "email_xyz789",
    "livemode": false
  }
}

Step 3: Watch it move through the pipeline

Within a few seconds the email goes queued → sent → delivered, with events in its timeline — exactly like production traffic:

curl https://api.tratto.email/v1/emails/email_xyz789 \
  -H "Authorization: Bearer tratto_test_..."

Special recipient addresses simulate the other outcomes:

RecipientOutcome
[email protected] (or any other address)delivered
[email protected]permanent bounce — email ends failed
[email protected]transient bounce
[email protected]spam complaint

If you have a webhook registered, these events are delivered to it too, with livemode: false in the payload. See Test mode for the full semantics.

Go live: verify your domain

Real email comes from a domain you own. Add it:

curl -X POST https://api.tratto.email/v1/domains \
  -H "Authorization: Bearer tratto_live_..." \
  -H "Content-Type: application/json" \
  -d '{"domain":"yourdomain.com"}'

Response (values are examples — always use the ones from your response):

{
  "data": {
    "id": "dom_abc123",
    "domain": "yourdomain.com",
    "status": "pending",
    "records": [
      { "type": "CNAME", "host": "token1._domainkey.yourdomain.com", "value": "token1.dkim.amazonses.com", "purpose": "dkim" },
      { "type": "CNAME", "host": "token2._domainkey.yourdomain.com", "value": "token2.dkim.amazonses.com", "purpose": "dkim" },
      { "type": "CNAME", "host": "token3._domainkey.yourdomain.com", "value": "token3.dkim.amazonses.com", "purpose": "dkim" },
      { "type": "TXT", "host": "yourdomain.com", "value": "v=spf1 include:amazonses.com ~all", "purpose": "spf" },
      { "type": "TXT", "host": "_dmarc.yourdomain.com", "value": "v=DMARC1; p=quarantine; rua=mailto:[email protected]", "purpose": "dmarc" }
    ]
  }
}

Add every record from the response at your DNS provider. The three DKIM CNAME records are required for verification; SPF and DMARC are strongly recommended for deliverability.

If your domain already has an SPF record (from Cloudflare Email Routing, Google Workspace, Microsoft 365 and similar), add include:amazonses.com to it instead of creating a second one, for example v=spf1 include:amazonses.com include:_spf.mx.cloudflare.net ~all. A domain must have exactly one v=spf1 record: two break SPF for every sender.

Amazon SES notes that DNS changes can take up to 72 hours to propagate. Verification also runs automatically: Tratto re-checks pending domains every 10 minutes.

Verify when ready:

curl -X POST https://api.tratto.email/v1/domains/dom_abc123/verify \
  -H "Authorization: Bearer tratto_live_..."

Once status is verified, swap your test key for a live one (tratto_live_...) — same code, real delivery. That's the only change.


Next Steps

Stuck? Check Error Codes or Authentication.


Edit this page on GitHub

Last updated on