"Example: welcome email via Plunk"
Send a welcome email to every newly-created OMMAX user.
Fires on user.human.added, sends a Plunk transactional email pointing the new user at Atrium.
Prereqs
- Plunk API key stored as a secret in
/admin/secrets:- Name:
PLUNK_API_KEY - Value: your Plunk private API key (
sk_...) - Allowed scripts:
welcome-new-hire(or leave empty for all)
- Name:
- Allowlist
api.useplunk.comon the runtime viaATRIUM_ACTIONS_FETCH_ALLOWLIST(already set)
Script
In /admin/actions:
- Name:
welcome-new-hire - Trigger type: EVENT
- Trigger name: user.human.added
- Secret refs:
PLUNK_API_KEY
// Welcome email — fires once per new user.
const u = ctx.payload.event_payload ?? {};
const email = u.email;
const firstName = u.firstName ?? u.userName ?? 'there';
if (!email) {
ctx.log.warn('no email in event_payload; skipping', { payload: ctx.payload });
return null;
}
const res = await ctx.fetch('https://api.useplunk.com/v1/send', {
method: 'POST',
headers: {
Authorization: `Bearer ${ctx.secrets.PLUNK_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
to: email,
subject: 'Welcome to OMMAX',
body: `
<h2>Hi ${firstName}, welcome to OMMAX</h2>
<p>Your accounts are live. Get started at
<a href="https://atrium.ommax-intelligence.de">Atrium</a> —
the directory of every OMMAX tool you have access to.</p>
<p>Questions? Hit us in #it-helpdesk on Slack.</p>
`,
}),
});
if (!res.ok) {
ctx.log.error('plunk failed', { status: res.status, body: await res.text() });
return { ok: false, status: res.status };
}
ctx.log.info('welcome email sent', { email });
return { ok: true };
Test before promoting
Use the "Test against sample payload" button (TODO when shipped) with this fixture:
{
"aggregateID": "111222333",
"event_type": "user.human.added",
"event_payload": {
"email": "you+test@ommax.de",
"firstName": "Test",
"userName": "you+test@ommax.de"
}
}
Make sure the Plunk send actually lands in your inbox before promoting to ACTIVE.
What can go wrong
PLUNK_API_KEYnot set or wrong → script returnsok:falsewith status 401. Fix in/admin/secrets.- Email already exists in Plunk's blocklist → 200 from Plunk but no delivery. Plunk dashboard tells you.
- Atrium runtime down → event lost (Zitadel doesn't retry). User onboarding still completes; they just don't get the email. Ops trade-off: acceptable for low-stakes notifications.
For higher-stakes notifications, consider mirroring this into a Slack channel as a backup signal.