Core Concepts
Understand the mental model of Tratto
Understand the foundational ideas behind Tratto before you start coding.
Tenant
A tenant is your isolated workspace. Everything you create (domains, templates, contacts, campaigns) belongs to a tenant. Each tenant:
- Has its own billing
- Supports multiple team members (with different permissions)
- Has separate API keys
- Cannot access other tenants' data
Think of it as your organization's "account", completely isolated from other customers.
API Key
An API key is a bearer token that authenticates your requests. Tratto API keys are prefixed tratto_live_ and are hashed when stored (we never store the raw key).
Key properties:
- Grant full workspace access, treat them like passwords
- Shown only once during creation
- Can be revoked at any time
- Should be rotated periodically for security
- Never expose them in client-side code
Authentication header:
Authorization: Bearer tratto_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxSee Authentication for managing keys.
Domain
A domain is a verified sending domain. Before you send emails, you must:
- Add your domain to Tratto
- Publish the DNS records from the API response: three DKIM CNAME records (required), plus SPF and DMARC (recommended)
- Wait for Tratto to verify DKIM: it re-checks every 10 minutes, or on demand
The records prove to receiving mail servers that you control the domain and are authorized to send from it.
Domain lifecycle:
pending: waiting for Amazon SES to find the DKIM recordsverified: ready to sendfailed: the DKIM records were not found
See Domains for step-by-step setup.
An email is an immutable send record. When you POST /v1/emails, Tratto:
- Validates the request (domain verified, rate limits, etc.)
- Creates an email document in Firestore
- Publishes an event to Pub/Sub
- Returns the email ID and status
The email then flows through the delivery pipeline.
Email status lifecycle:
┌─ delivered ─┐
│ │
▼ ▼
queued ─→ scheduled ─→ sent ─┤─ opened (tracking)
│ │─ clicked (tracking)
│ │─ bounced
│ │─ complained
▼ └─ unsubscribed
failedStatus definitions:
queued: Email is in the queue, will be sent shortlyscheduled: Email is scheduled for future deliverysent: Email was sent to the mail serverdelivered: Mail server confirmed delivery (bounce-free)failed: Delivery failed (invalid domain, etc.)
See Email Status & Lifecycle for more.
Events
Events are tracking records for what happened to an email. Unlike status (the email state), events are discrete actions:
sent: Email was sent to mail serverdelivered: Mail server confirmed receiptopened: Recipient opened the email (pixel tracked)clicked: Recipient clicked a linkbounced: Mail server rejected deliverycomplained: Recipient marked as spamunsubscribed: Recipient clicked unsubscribe
You get events via:
- Webhooks: Real-time HTTP push notifications
- Email events API:
GET /v1/emails/{id}/events
See Webhooks for setup.
Webhook
A webhook is an HTTP endpoint you control that Tratto calls when an email event occurs. You register a webhook URL, and Tratto POSTs event payloads to it.
Event payload example:
{
"id": "evt_abc123",
"type": "delivered",
"emailId": "email_xyz789",
"recipient": "[email protected]",
"occurredAt": "2025-06-30T12:00:00Z"
}Security:
- Payloads are signed with HMAC-SHA256 in the
x-tratto-signatureheader - Always verify the signature before processing
- Replay attacks: check the
occurredAttimestamp
See Webhooks for signature verification code.
Template
A template is a versioned email template with placeholder variables. Instead of composing HTML in code, you create a template in Tratto and reference it by ID.
Template structure:
Subject: Welcome {{firstName}}!
HTML: <h1>Hello {{firstName}} {{lastName}}</h1>
<p>Your code: {{code}}</p>Usage:
{
"from": "[email protected]",
"to": "[email protected]",
"templateId": "tmpl_abc123",
"variables": {
"firstName": "Alice",
"lastName": "Smith",
"code": "12345"
}
}Versioning:
- Each template update creates a new version
- You can restore previous versions
- Campaigns and flows reference a template version
See Templates for full docs.
Flow
A flow is an automation engine. Create a workflow that triggers on events (contact joins audience, email opened, etc.) and executes steps (send email, wait, branch, update contact).
Flow structure:
Trigger (e.g., contact_joins_audience)
↓
Step 1 (e.g., send_email)
↓
Step 2 (e.g., wait 3 days)
↓
Step 3 (e.g., send another email)
↓
Step 4 (e.g., branch on email_opened)
├─ True path → send email
└─ False path → do nothingKey features:
- Trigger types:
contact_joins_audience,email_event,contact_tag_added,manual - Step types:
send_email,wait,branch,update_contact,webhook_call - Enrolled contacts: track who is in the flow
- Activate/deactivate flows without losing enrollment data
See Flows for detailed setup.
Campaign
A campaign is a one-time email broadcast to an audience. Create a campaign, optionally test-send it, then send it to all contacts in an audience.
Campaign lifecycle:
draft → (optional test send) → send → scheduled → sending → sentKey properties:
name: Campaign nametemplateId: Which template to useaudienceId: Who receives itsendAt: Schedule for later (optional)status: Current state
After sending:
- Get delivery stats:
GET /v1/campaigns/{id}/stats - View individual email events
- Cannot be re-sent (create a new campaign instead)
See Campaigns for details.
Audience
An audience is a group of contacts, created via rule-based filters or manual additions.
Rule types:
status:subscribed,unsubscribed,bounced,complainedtags: Filter by contact tags (e.g., "vip", "newsletter")metadata: Custom fields (e.g.,plan: "pro")dateRange: Contacts created between dates
Dynamic vs static:
- Dynamic: Rules re-evaluated, membership changes automatically
- Static: Fixed list, doesn't update
Usage:
- Campaigns: send to an audience
- Flows: trigger when contact joins audience
See Audiences for setup.
Next Steps
- Authentication? Start with API Keys & Auth
- Ready to send? Go to Quickstart
- Deep dive? Explore individual concepts:
Edit this page on GitHub
Last updated on