Sendry Docs

Automations

Event-triggered email workflows. Send multi-step sequences when something happens in your app.

Sendry Automations let you fire an event from your app and have Sendry run a multi-step workflow per contact — send an email, wait, branch on a condition, or split into an A/B test.

A typical use case: a user signs up, your backend fires user.signed_up, and Sendry automatically sends a welcome email, waits a day, then sends a tips email.

Automations are available on the Pro plan and above. The Free plan does not include automations.

Concepts

TermMeaning
AutomationA workflow tied to a trigger.
StepAn ordered action inside an automation: send_email, wait, branch, or ab_split.
RunOne execution of an automation for one contact.
TriggerWhat starts a run — either an event match or a contact being added to a segment.
Re-entryWhether a contact can run the same automation more than once.

Trigger types

TypeFires when
eventAn event with a matching name and payload conditions is sent to POST /v1/events.
contact_added_to_segmentA contact enters a specific segment.

Re-entry policies

PolicyBehavior
once_per_contactA given contact can run this automation at most once. Subsequent triggers are ignored.
cooldownA contact can re-enter after cooldown_seconds have passed since the last run.
alwaysEvery matching trigger creates a new run.

Status

StatusDescription
draftSaved but not yet active. Triggers are ignored.
activeTriggers create runs.
pausedExisting runs continue, but new triggers are ignored.
archivedHidden from the dashboard. New triggers ignored. Run history retained.

Quickstart

1. Create an automation

In the dashboard, open Automations and click New Automation. The visual builder lets you drop in a trigger and chain steps without writing JSON.

You can also create one via the API:

curl -X POST https://api.sendry.online/v1/automations \
  -H "Authorization: Bearer $SENDRY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Welcome series",
    "trigger": {
      "type": "event",
      "event_name": "user.signed_up"
    },
    "reentry_policy": "once_per_contact"
  }'

2. Add steps

Build a sequence: send a welcome email, wait one day, send a follow-up tip.

# Step 1: welcome email
curl -X POST https://api.sendry.online/v1/automations/auto_abc123/steps \
  -H "Authorization: Bearer $SENDRY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "send_email",
    "config": {
      "from": "Acme <hello@acme.com>",
      "subject": "Welcome to Acme, {{first_name}}!",
      "html": "<h1>Hi {{first_name}}</h1><p>Glad you joined.</p>",
      "message_type": "marketing"
    }
  }'

# Step 2: wait 24 hours
curl -X POST https://api.sendry.online/v1/automations/auto_abc123/steps \
  -H "Authorization: Bearer $SENDRY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "wait",
    "config": { "duration_seconds": 86400 }
  }'

# Step 3: tips email
curl -X POST https://api.sendry.online/v1/automations/auto_abc123/steps \
  -H "Authorization: Bearer $SENDRY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "send_email",
    "config": {
      "template_id": "tpl_tips_day1",
      "from": "Acme <hello@acme.com>",
      "message_type": "marketing"
    }
  }'

3. Activate it

curl -X PATCH https://api.sendry.online/v1/automations/auto_abc123 \
  -H "Authorization: Bearer $SENDRY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "active" }'

4. Fire the event from your app

Whenever a user signs up, send the event. Sendry looks up (or creates) the contact by contact_email and starts a run.

await sendry.events.send({
  name: "user.signed_up",
  contact_email: "jane@acme.com",
  properties: { plan: "pro", first_name: "Jane" },
});
client.events.send(
    name="user.signed_up",
    contact_email="jane@acme.com",
    properties={"plan": "pro", "first_name": "Jane"},
)
curl -X POST https://api.sendry.online/v1/events \
  -H "Authorization: Bearer $SENDRY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "user.signed_up",
    "contact_email": "jane@acme.com",
    "properties": {"plan": "pro", "first_name": "Jane"}
  }'

That's it — Sendry handles the rest. Inspect runs in the dashboard or via GET /v1/automations/:id/runs.

Step type reference

Each step has a type and a config object whose shape depends on the type.

send_email

Sends an email to the contact triggering the run. Either template_id or both subject and a body (html/text) must be provided.

FieldTypeRequiredDescription
template_idstringNo*Saved template ID. Mutually exclusive with subject + html/text.
subjectstringNo*Subject line. Required if no template_id.
htmlstringNo*HTML body. At least one of html or text is required if no template.
textstringNoPlain-text body.
fromstringYesSender. Domain must be verified.
reply_tostringNoReply-to address.
message_typestringNotransactional or marketing. Default marketing.
topic_idstringNoSubscription topic — recipients unsubscribed from this topic are skipped.
variablesobjectNoExtra template variables. Merged with event properties + contact fields.

Variables in the body use {{variable_name}} syntax. Available by default: contact fields (first_name, email, etc.) and the event properties payload.

wait

Pauses the run for a fixed duration.

FieldTypeRequiredDescription
duration_secondsnumberYesSeconds to wait before running the next step.

Common values: 3600 (1 hour), 86400 (1 day), 604800 (1 week).

branch

Splits the run path based on a condition. The next step continues if the condition is true; otherwise the run ends (or jumps to a configured "else" branch in the visual builder).

FieldTypeRequiredDescription
conditionobjectYesCondition object (see below).

Condition operators:

OperatorFieldsMatches if
property_eqproperty, valueThe given property equals value.
property_existspropertyThe given property is set (non-null).

Properties are looked up first in the event payload, then on the contact.

{
  "type": "branch",
  "config": {
    "condition": {
      "op": "property_eq",
      "property": "plan",
      "value": "pro"
    }
  }
}

ab_split

Splits incoming runs between two paths by weight. Useful for A/B-testing subject lines or content.

FieldTypeRequiredDescription
split{ a: number, b: number }YesWeights for branch A and branch B. They are normalized.
seedstringNoOptional seed for deterministic bucketing per contact.
{
  "type": "ab_split",
  "config": {
    "split": { "a": 50, "b": 50 },
    "seed": "subject-test-2026-q1"
  }
}

API reference

All automation endpoints require Authorization: Bearer <api_key>. Mutation endpoints require full_access scope; reads accept read_only and above.

MethodEndpointDescription
POST/v1/automationsCreate an automation.
GET/v1/automationsList automations (cursor-paginated).
GET/v1/automations/:idGet one automation.
PATCH/v1/automations/:idUpdate fields like status, name, trigger.
DELETE/v1/automations/:idArchive (soft-delete) an automation.
POST/v1/automations/:id/stepsAppend a step.
GET/v1/automations/:id/stepsList steps in execution order.
GET/v1/automations/:id/runsList per-contact runs for an automation.
POST/v1/eventsFire an event. Most apps only need this endpoint.

Event payload

{
  "name": "user.signed_up",
  "contact_email": "jane@acme.com",
  "properties": {
    "plan": "pro",
    "first_name": "Jane"
  }
}
FieldTypeRequiredDescription
namestringYesEvent name. Match this against an automation trigger.
contact_emailstringYesContact identifier. Created automatically if it doesn't exist.
propertiesobjectNoArbitrary key/value payload. Available to step variables and conditions.

Run object

{
  "id": "run_abc123",
  "automation_id": "auto_abc123",
  "contact_id": "ct_xyz789",
  "status": "in_progress",
  "current_step_index": 1,
  "started_at": "2026-05-10T09:00:00Z",
  "completed_at": null,
  "next_run_at": "2026-05-11T09:00:00Z"
}

Run status values: in_progress, completed, cancelled, failed.

Use cases

  • Welcome dripuser.signed_up → welcome email → wait 1 day → tips email → wait 3 days → "ready to upgrade?" email.
  • Cart abandonmentcart.abandoned → wait 1 hour → reminder email → wait 24 hours → discount email (branch on cart.recovered).
  • Post-purchase follow-uporder.delivered → wait 3 days → "how was it?" email → wait 7 days → review request.
  • Behavioral onboardingfeature.first_used → contextual tip email; feature.unused_after_7_days → nudge email.
  • Re-engagementcontact_added_to_segment (segment: "inactive 30 days") → re-engagement email → branch on email.clicked.

Plan limits

PlanAutomationsActive runs / mo
FreeNot available
Pro2550,000
Business250500,000
EnterpriseUnlimitedCustom

On this page