Sending email
Mailpark sends two kinds of email on separate lanes, so a marketing problem can never delay a password reset.
Transactional and marketing
| Transactional | Marketing | |
|---|---|---|
| What | Triggered by one person's action: resets, receipts, invites, alerts. | Updates, tips, onboarding, announcements. |
| Sent from | mail.yourdomain.com | updates.yourdomain.com |
| Unsubscribe link | No | Always, plus a one-click List-Unsubscribe header. |
| Limits | Never held back by marketing limits. | Daily limit by trust level, spending cap, topic opt-outs. |
| Opens and clicks | Recorded | Recorded |
Templates and variables
Write {{variable}} anywhere in a template's subject, preview text or body. Each value comes from, in order: the send's data, the contact's fields, then the template's declared default. {{first_name|there}} sets an inline fallback.
await mailpark.templates.create({
key: "trial-ending",
type: "marketing",
subject: "Your {{product_name}} trial ends in 3 days",
source: "<p>Hi {{first_name|there}}, your trial ends on {{trial_end}}.</p>",
variables: [{ name: "trial_end", description: "Date the trial ends" }],
});
const preview = await mailpark.templates.preview("trial-ending", { trial_end: "Oct 25" });
console.log(preview.missing_variables); // [] when everything is filledEvery update publishes a new version. Sends use the latest version and record which one they used.
Topics and consent
Give each kind of marketing email a topic, such as product-updates or onboarding. Recipients can leave one topic without leaving them all. Mailpark skips anyone who unsubscribed, bounced or complained; those sends come back as suppressed rather than as errors.
Emailing many people
Broadcasts
For one email to many people, draft a broadcast. A person approves it in the web app; then Mailpark sends to a small sample first, checks bounces and complaints, and sends the rest.
Sequences
For emails that follow what people do, create a sequence triggered by an event such as signed_up. Record events from your app, and Mailpark sends each step at the right time.
// In your signup handler:
await mailpark.contacts.upsert({ email: user.email, external_id: user.id, fields: { first_name: user.firstName } });
await mailpark.events.record({ name: "signed_up", email: user.email });POST /v1/emails in a loop to reach a list skips approval, test sends and topic checks. Use a broadcast instead.Checking delivery
- GET /v1/emails/{id} shows every stage with times.
- GET /v1/emails/{id}/explain answers "why didn't they get it?" in plain words.
- Webhooks push deliveries, bounces and complaints to your app as they happen.