Automated Sequences
Sequences are automated drip campaigns that enroll contacts based on trigger events. Each sequence contains ordered steps with configurable delays, supporting both email and SMS channels.
Sequence model
Section titled “Sequence model”| Field | Type | Description |
|---|---|---|
id | UUID | Primary key |
foundation_id | UUID | Owning foundation |
name | string | Sequence name (e.g., “New Donor Welcome”) |
trigger | SequenceTrigger | Event that enrolls contacts |
status | string | active or paused |
Triggers
Section titled “Triggers”The SequenceTrigger enum defines which contact events automatically enroll contacts:
| Value | Description |
|---|---|
donation_received | Contact makes a donation |
application_submitted | Contact submits a scholarship application |
subscriber_added | Contact is assigned the subscriber relationship |
donation_failed | A recurring donation payment fails |
Sequence steps
Section titled “Sequence steps”Each sequence contains ordered SequenceStep records:
| Field | Type | Description |
|---|---|---|
id | UUID | Primary key |
sequence_id | UUID | Parent sequence |
position | integer | Order in the sequence (1-based) |
channel | CampaignChannel | email or sms |
subject | string? | Email subject line (null for SMS) |
body | string | Message body (supports merge fields) |
delay_hours | integer | Hours to wait before executing this step |
Steps are always ordered by position. The delay_hours on each step is relative to enrollment time (step 1) or the previous step’s execution.
Example sequence: New Donor Welcome
Section titled “Example sequence: New Donor Welcome”| Position | Channel | Delay | Subject | Body |
|---|---|---|---|---|
| 1 | 0 hours | Thank you, (first_name)! | Welcome email with donation receipt | |
| 2 | 72 hours | Your impact at (foundation_name) | Impact report / how funds are used | |
| 3 | SMS | 168 hours | — | Quick check-in text message |
Enrollment
Section titled “Enrollment”The SequenceService::enroll() method creates an enrollment record:
public function enroll(Contact $contact, Sequence $sequence): SequenceEnrollment;The enrollment:
- Finds the first step (lowest position)
- Creates a
SequenceEnrollmentwithstatus: active - Sets
next_step_attonow() + firstStep->delay_hours - If the sequence has no steps, marks enrollment as completed immediately
SequenceEnrollment model
Section titled “SequenceEnrollment model”| Field | Type | Description |
|---|---|---|
id | UUID | Primary key |
sequence_id | UUID | The sequence |
contact_id | UUID | The enrolled contact |
foundation_id | UUID | Foundation scope |
current_step_id | UUID? | The step currently queued |
status | string | active, completed, or cancelled |
next_step_at | datetime? | When the current step should execute |
enrolled_at | datetime | When the contact was enrolled |
completed_at | datetime? | When the sequence finished |
Step processing
Section titled “Step processing”The SequenceService::processDue() method runs on a schedule (via Laravel’s scheduler or queue worker):
public function processDue(): void;It:
- Finds all active enrollments where
next_step_at <= now() - Dispatches a
ProcessSequenceStepjob for each
The ProcessSequenceStep job:
- Sends the message via
EmailServiceorSmsServicebased on the step’s channel - Finds the next step in the sequence (by position)
- If a next step exists, updates
current_step_idandnext_step_at - If no next step exists, marks the enrollment as
completed
Merge fields
Section titled “Merge fields”Sequence step bodies support the same merge placeholders as campaigns and templates:
first_name, last_name, and foundation_name. See Message Templates for the full reference.
Plan limits
Section titled “Plan limits”| Plan | Max sequences |
|---|---|
| Starter | 2 |
| Growth | 10 |
| Pro | Unlimited |
API endpoints
Section titled “API endpoints”| Method | Path | Description |
|---|---|---|
| GET | /api/sequences | List sequences |
| POST | /api/sequences | Create a sequence |
| GET | /api/sequences/{id} | Show a sequence with steps |
| PUT | /api/sequences/{id} | Update a sequence |
| DELETE | /api/sequences/{id} | Delete a sequence |
| POST | /api/sequences/{id}/steps | Add a step to a sequence |
| PUT | /api/sequences/{id}/steps/{step} | Update a step |
| DELETE | /api/sequences/{id}/steps/{step} | Delete a step |