Skip to content

Email triggers

A trigger sends one project email when a selected event fires. Use it for notifications such as “email the owner when an order is created”. Triggers use the same events as webhooks and run next to them: an event that reaches your webhooks also reaches your triggers, and a failed email never fails the original API call.

Configure triggers in the console under Database → Automation → Triggers, or with the admin API below. The Automation tab has two sub-tabs, Webhooks and Triggers.

Mail goes out from the project’s own address, for example "Acme Shop" <acme-shop-a1b2c3@tefily.com>. The display name is the project name, and the address is shown in Project Settings → Project details. There is no inbox behind the address, and you cannot choose a different sender or a reply-to.

Pick at least one of the events on Webhooks, except webhook.ping. Collections work as they do for webhooks: leave the list empty for every collection. Auth events ignore the collection filter.

Mode recipientMode Setting Meaning
Fixed address value recipientValue Always the same address.
From the record record recipientField Read the address from the event data.

This mirrors the “compare with a record field or a static value” choice in access rules.

For recordField, a bare name (email, ownerEmail) is looked up on the record, then on the user, then on the event data itself. A dotted name (record.ownerEmail, user.email) starts at the event data. Auth events carry the end user, so email resolves to the user’s address.

Bulk events (record.created_many, and so on) have no single record, so a trigger that reads its recipient from the record is skipped for them. A fixed address sends once per event.

If the field is missing or is not a valid email address, the send is skipped and the reason is logged on the trigger. It never fails the original request.

subjectTemplate and bodyTemplate accept placeholders in double braces. Unknown placeholders render empty.

Placeholder Value
{{event}} The event name
{{collection}} The collection, empty for auth events
{{projectName}} The project name
{{timestamp}} When the event fired (UTC)
{{record.title}} A field of the record. Any field works.
{{user.email}} A field of the end user, for auth events

Set bodyIsHtml to send the body as HTML. Substituted values are HTML-escaped, the template itself is not. Otherwise the body is plain text. Subjects are one line, at most 200 characters. Values are cut at 2,000 characters.

  • At most 20 triggers per project. Create beyond the cap fails with A project may have at most 20 email triggers.
  • Each trigger email counts toward max_transactional_emails_per_day, the same daily cap as the send API. Over the cap the email is not sent and the run is logged as failed.

See Usage and limits.

Every attempt is recorded on the trigger with sent, skipped, or failed, the event, the recipient, and the reason. The console shows the latest 50. Runs older than 30 days are removed over time.

Requires a platform JWT or PAT with schema read (list, get, runs) or schema update (create / update / delete / test).

Method Path
GET / POST /api/projects/:projectId/email-triggers
GET / PATCH / DELETE /api/projects/:projectId/email-triggers/:id
GET /api/projects/:projectId/email-triggers/:id/runs
POST /api/projects/:projectId/email-triggers/:id/test
POST /api/projects/YOUR_PROJECT_ID/email-triggers
Authorization: Bearer kfx_…
Content-Type: application/json
{
"name": "New order",
"events": ["record.created"],
"collections": ["orders"],
"recipientMode": "record",
"recipientField": "customerEmail",
"subjectTemplate": "Order {{record.number}} received",
"bodyTemplate": "Thanks, we have your order {{record.number}}.",
"bodyIsHtml": false,
"isActive": true
}

test sends the templates once to the signed-in user, with sample data, so you can check the sender and wording without firing a real event. It counts toward the daily cap.