SaaS Customer Onboarding
A 14-day onboarding sequence that sends a welcome email, waits for activation, branches by user engagement, A/B tests subject lines, alerts your team on churn risk, and updates your CRM.
What this workflow does
Welcome email — sends immediately after signup via SendGrid or Gmail (Activepieces connector).
Wait 2 days — business-hours-only delay. Skips weekends.
Check activation — HTTP request to your API to check if the user completed setup.
Branch — activated users get a tips-and-tricks email. Non-activated get a nudge with A/B tested subject lines (60/40 split).
Wait 5 more days — then check engagement score via your analytics API.
Churn risk alert — if engagement is low, Slack notification to #customer-success with user details.
CRM update — updates HubSpot contact lifecycle stage via Activepieces connector.
Workflow definition
Copy this JSON and POST it to /sequences.
{
"id": "saas_onboarding_v1",
"context_schema": {
"user_id": "string",
"email": "string",
"name": "string",
"plan": "string"
},
"blocks": [
{
"id": "welcome_email",
"type": "step",
"handler": "ap://sendgrid.send_email",
"params": {
"auth": { "api_key": "credentials://sendgrid" },
"props": {
"to": "{{context.data.email}}",
"subject": "Welcome to {{context.data.plan}}, {{context.data.name}}!",
"html": "<h1>You're in!</h1><p>Here's how to get started...</p>"
}
}
},
{
"id": "wait_activation",
"type": "step",
"handler": "sleep",
"params": { "duration_ms": 172800000 },
"delay": { "duration": 172800000, "business_days_only": true }
},
{
"id": "check_activation",
"type": "step",
"handler": "http_request",
"params": {
"method": "GET",
"url": "https://api.yourapp.com/users/{{context.data.user_id}}/activation",
"headers": { "Authorization": "Bearer credentials://internal-api" }
}
},
{
"id": "activation_branch",
"type": "router",
"routes": [
{
"condition": "steps.check_activation.output.activated",
"blocks": [
{
"id": "tips_email",
"type": "step",
"handler": "ap://sendgrid.send_email",
"params": {
"auth": { "api_key": "credentials://sendgrid" },
"props": {
"to": "{{context.data.email}}",
"subject": "3 tips to get more from {{context.data.plan}}",
"html": "<h1>Power user tips</h1><p>...</p>"
}
}
}
]
}
],
"default": [
{
"id": "nudge_ab",
"type": "ab_split",
"variants": [
{
"name": "nudge_a", "weight": 60,
"blocks": [
{
"id": "nudge_a_email",
"type": "step",
"handler": "ap://sendgrid.send_email",
"params": {
"auth": { "api_key": "credentials://sendgrid" },
"props": {
"to": "{{context.data.email}}",
"subject": "You're 1 step away from setup",
"html": "<p>Complete your setup in 2 minutes...</p>"
}
}
}
]
},
{
"name": "nudge_b", "weight": 40,
"blocks": [
{
"id": "nudge_b_email",
"type": "step",
"handler": "ap://sendgrid.send_email",
"params": {
"auth": { "api_key": "credentials://sendgrid" },
"props": {
"to": "{{context.data.email}}",
"subject": "Need help getting started?",
"html": "<p>Reply to this email — we'll set it up for you.</p>"
}
}
}
]
}
]
}
]
},
{
"id": "wait_engagement",
"type": "step",
"handler": "sleep",
"params": { "duration_ms": 432000000 },
"delay": { "duration": 432000000 }
},
{
"id": "check_engagement",
"type": "step",
"handler": "http_request",
"params": {
"method": "GET",
"url": "https://api.yourapp.com/users/{{context.data.user_id}}/engagement",
"headers": { "Authorization": "Bearer credentials://internal-api" }
}
},
{
"id": "churn_branch",
"type": "router",
"routes": [
{
"condition": "steps.check_engagement.output.score < 30",
"blocks": [
{
"id": "churn_alert",
"type": "step",
"handler": "ap://slack.send_channel_message",
"params": {
"auth": { "access_token": "credentials://slack-bot" },
"props": {
"channel": "#customer-success",
"text": "Churn risk: {{context.data.name}} ({{context.data.email}}) — engagement score {{steps.check_engagement.output.score}}/100. Plan: {{context.data.plan}}"
}
}
}
]
}
]
},
{
"id": "crm_update",
"type": "step",
"handler": "ap://hubspot.update_contact",
"params": {
"auth": { "access_token": "credentials://hubspot-oauth" },
"props": {
"email": "{{context.data.email}}",
"properties": {
"lifecyclestage": "customer",
"onboarding_completed": true
}
}
}
}
]
}Credentials to configure
Register these via POST /credentials before deploying.
sendgridapi_keySendGrid API key for transactional emailsslack-botoauth2Slack bot token with chat:write scopehubspot-oauthoauth2HubSpot OAuth2 token with crm.objects.contacts.writeinternal-apiapi_keyYour app's internal API key for activation/engagement checksHow to trigger
Fire this workflow when a new user signs up.
// POST /instances
{
"sequence_id": "saas_onboarding_v1",
"context": {
"user_id": "usr_abc123",
"email": "alice@example.com",
"name": "Alice",
"plan": "Pro"
},
"idempotency_key": "onboarding:usr_abc123"
}Or attach a webhook trigger to fire on your signup event:
// POST /triggers
{
"type": "webhook",
"sequence_id": "saas_onboarding_v1",
"config": {
"path": "/hooks/new-signup",
"hmac_secret": "credentials://webhook-secret"
},
"context_mapping": {
"user_id": "body.user.id",
"email": "body.user.email",
"name": "body.user.name",
"plan": "body.user.plan"
}
}Customize it
Swap email provider — replace ap://sendgrid.send_email with ap://gmail.send_email or ap://mailchimp.send_email.
Add more branches — check plan tier in the router to send different content to Free vs Pro vs Enterprise users.
Extend the timeline — add more delay + email steps to create a 30-day or 60-day onboarding drip.
Add retry — wrap email steps in a TryCatch block with exponential backoff if your provider has rate limits.