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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

See Authentication for managing keys.

Domain

A domain is a verified sending domain. Before you send emails, you must:

  1. Add your domain to Tratto
  2. Publish the DNS records from the API response: three DKIM CNAME records (required), plus SPF and DMARC (recommended)
  3. 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 records
  • verified: ready to send
  • failed: the DKIM records were not found

See Domains for step-by-step setup.

Email

An email is an immutable send record. When you POST /v1/emails, Tratto:

  1. Validates the request (domain verified, rate limits, etc.)
  2. Creates an email document in Firestore
  3. Publishes an event to Pub/Sub
  4. 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
                            failed

Status definitions:

  • queued: Email is in the queue, will be sent shortly
  • scheduled: Email is scheduled for future delivery
  • sent: Email was sent to the mail server
  • delivered: 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 server
  • delivered: Mail server confirmed receipt
  • opened: Recipient opened the email (pixel tracked)
  • clicked: Recipient clicked a link
  • bounced: Mail server rejected delivery
  • complained: Recipient marked as spam
  • unsubscribed: 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-signature header
  • Always verify the signature before processing
  • Replay attacks: check the occurredAt timestamp

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 nothing

Key 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 → sent

Key properties:

  • name: Campaign name
  • templateId: Which template to use
  • audienceId: Who receives it
  • sendAt: 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, complained
  • tags: 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


Edit this page on GitHub

Last updated on