Quickstart
Go from zero to a sent email: sign in, connect a sender, create a product, design a template, attach a webhook, and fire a signed trigger from your service.
1. Sign in
Sign in to your workspace via Elixpo Accounts (SSO). Your workspace is your tenant — senders, products, and templates all live under it.
2. Add a sender
Connect the mailbox mail will be sent from — your Gmail or any SMTP account, using an app password (not your login password). Elixpo Mails never relays through a shared pool; every email goes out as you.
3. Create a product
A product groups your templates and carries one shared signing secret. On creation you receive a client_id and a shared secret shown once.
Save the secret now
4. Design a template
Build the email in the lixeditor WYSIWYG editor. Drop {{variables}} into the subject and body — e.g. Hi {{name}}, your order {{order_id}} shipped. Elixpo Mails derives the variable list from the template automatically. Set the transactional flag for essential mail like receipts and password resets.
5. Add a webhook to the template
Attach a webhook to the template. You get a signed endpoint identified by an endpoint_key (shown on the webhook), which forms your trigger URL: https://mails.elixpo.com/v1/hooks/<endpoint_key>.
6. Sign & POST a trigger
From your service, HMAC-sign the request with the product secret and POST the trigger. Build the JSON body once, sign over `${t}.${rawBody}`, and send the same bytes.
import crypto from "node:crypto";
const secret = "YOUR_PRODUCT_SECRET";
const url = "https://mails.elixpo.com/v1/hooks/whe_xxx";
// Build the body ONCE — sign and send the exact same bytes.
const payload = JSON.stringify({ to: "user@example.com", variables: { name: "Ada" } });
const t = Math.floor(Date.now() / 1000);
const v1 = crypto.createHmac("sha256", secret).update(`${t}.${payload}`).digest("hex");
const res = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Elixpo-Signature": `t=${t},v1=${v1}`,
},
body: payload,
});
const out = await res.json();
// { ok: true, id, status: "sent", to, subject }200 { ok: true, status: "sent" }— the email was sent.200 { ok: false, status: "suppressed" }— recipient unsubscribed; a successful no-op.502 { ok: false, status: "failed", error }— downstream send failure.
