Express.js API that publishes user events to Knock.app for intelligent notification orchestration.
Watch the complete setup and demo - Step-by-step video explaining the architecture, code walkthrough, and Knock dashboard configuration.
Event Publisher Pattern: API publishes classified events to Knock. Knock workflows handle all notification logic including conditional delivery and smart scheduling based on user profile data.
API Event โ Knock Workflow โ Conditional Logic โ Scheduled Notification
npm install
cp .env.example .env
# Add your KNOCK_SECRET_KEY
npm startknock-notifications/
โโโ routes/
โ โโโ users.js # User event endpoints
โโโ server.js # Express server
โโโ package.json # Dependencies
โโโ .env.example # Environment template
โโโ README.md # This file
- API publishes events (not direct notifications)
- Knock receives event and checks user profile data
- Workflow executes conditionally based on field existence
- Notifications scheduled using user's actual timestamps
Publishes user_created event with user profile data.
curl -X POST http://localhost:3000/api/users/onboard \
-H "Content-Type: application/json" \
-d '{
"userId": "user123",
"userEmail": "[email protected]",
"userName": "John Doe",
"userCreatedAt": "2025-01-15T10:30:00Z",
"planType": "premium",
"signupSource": "mobile"
}'Response:
{
"success": true,
"user_profile": {
"id": "user123",
"email": "[email protected]",
"name": "John Doe",
"created_at": "2025-01-15T10:30:00Z",
"plan_type": "premium",
"signup_source": "mobile"
}
}Generic event publisher for any workflow trigger.
curl -X POST http://localhost:3000/api/users/event \
-H "Content-Type: application/json" \
-d '{
"userId": "user123",
"eventType": "first_login",
"eventData": {"device": "mobile"}
}'Retrieve user profile from Knock.
Update user profile via user_profile_updated event.
- Branch Step: Check if
recipient.created_atexists (not_emptyoperator) - Delay Step: Fixed interval or calculated from timestamp
- Email Step: Welcome email with user data
if (recipient.created_at exists) {
wait(delay_duration)
send_welcome_email()
} else {
do_nothing()
}
{{ recipient.name }}- User's name{{ recipient.email }}- User's email{{ recipient.plan_type }}- Subscription plan{{ recipient.signup_source }}- How they signed up{{ recipient.created_at }}- Account creation timestamp
KNOCK_SECRET_KEY=sk_test_your_knock_api_key
PORT=3000- Decoupled: API doesn't contain notification logic
- Flexible: Add new workflows without code changes
- Smart: Workflows access full user profile context
- Conditional: Logic based on user data existence
- Scalable: Knock handles delivery, retries, and scheduling
Unlike traditional "send in X time from now" approaches, this system uses the user's actual creation timestamp for scheduling:
// Traditional approach - delay from current time
delay_until: now() + 2_days
// This system - delay from user's creation time
delay_until: recipient.created_at + 2_daysThis enables accurate lifecycle messaging regardless of when events are triggered.
- Express.js - API server
- Knock.app - Notification orchestration
- Event-driven architecture - Scalable pattern