Setting up MailBlastr for multi-tenant apps
Two patterns for SaaS apps that send on behalf of tenants: a single MailBlastr account with domain-scoped keys, or separate accounts (BYOK). Trade-offs in isolation, billing, and deliverability.
Many SaaS platforms need to send email on behalf of their tenants — transactional notifications, onboarding sequences, or campaigns from a tenant’s own domain. There are two main ways to configure MailBlastr for this. Neither is universally "right"; the best choice depends on how much control you want and what your tenants need.
At a glance
| Factor | Single account | Separate accounts / BYOK |
|---|---|---|
| Setup complexity | Low — fully API-driven | Higher — manual account per tenant |
| Sending isolation | Shared — one bad actor affects all | Full — each tenant isolated |
| Billing | One plan covers all tenants | Each tenant manages their own plan |
| Per-tenant analytics | Not native | Each tenant has its own dashboard |
| Webhook routing | Via tags or from domain | Each account has its own webhooks |
| Deliverability | Shared sender reputation | Independent sender reputation |
| Rate limits | Aggregate — likely needs an increase | Each tenant uses their own limits |
Option A: a single MailBlastr account
You manage everything from one account: add each tenant’s domain, verify it, and mint a domain-scoped API key so each tenant can only send from their own domain. All sending, billing, and analytics flow through your account. The whole flow is API-driven.
When a tenant signs up, create and verify their domain.
1. Create the tenant's domain:
import { MailBlastr } from 'mailblastr';
const mb = new MailBlastr('mb_xxxxxxxxx');
const { data, error } = await mb.domains.create({ "name": "tenant-domain.com" });
console.log({ data, error });2. After the tenant publishes the DNS records, trigger verification:
import { MailBlastr } from 'mailblastr';
const mb = new MailBlastr('mb_xxxxxxxxx');
const { data, error } = await mb.domains.verify('DOMAIN_ID');
console.log({ data, error });Once verified, create a sending_access key scoped to that domain so the tenant can only send from it:
import { MailBlastr } from 'mailblastr';
const mb = new MailBlastr('mb_xxxxxxxxx');
const { data, error } = await mb.apiKeys.create({
"name": "Tenant: tenant-domain.com",
"permission": "sending_access",
"domain_id": "DOMAIN_ID"
});
console.log({ data, error });- Pros: seamless API-driven setup; domain-scoped keys confine each tenant to their own domain; one account to manage.
- Cons: no per-tenant analytics in the dashboard; tenants share your sender reputation; aggregate volume will likely need a quota increase.
Option B: separate accounts (BYOK)
In the Bring-Your-Own-Key model, each tenant creates their own MailBlastr account, adds their domain, and gives you their API key. Your app stores each tenant’s key and uses it when sending for them:
import { MailBlastr } from 'mailblastr';
// Look up the calling tenant's own MailBlastr key, then send with it.
const tenantApiKey = await getTenantKey(tenantId);
const mb = new MailBlastr(tenantApiKey);
await mb.emails.send({
from: 'notifications@tenant-domain.com',
to: ['user@example.com'],
subject: 'Your order has shipped',
html: '<p>Your order #1234 is on its way.</p>',
});- Pros: full isolation — each tenant’s reputation and deliverability are independent; no liability for tenant behavior on your account; each tenant has their own dashboard and rate limits.
- Cons: each tenant must create and manage their own account and plan, which adds onboarding friction for those unfamiliar with email infrastructure.
Webhook routing
With Option A, attach a tenant identifier as a tag when sending; tags are echoed in webhook payloads, so you can route events back to the right tenant:
import { MailBlastr } from 'mailblastr';
const mb = new MailBlastr('mb_xxxxxxxxx');
const { data, error } = await mb.emails.send({
"from": "notifications@tenant-domain.com",
"to": ["user@example.com"],
"subject": "Welcome aboard",
"html": "<p>Thanks for signing up.</p>",
"tags": [{ "name": "tenant_id", "value": "tenant_abc123" }]
});
console.log({ data, error });With Option B, each tenant configures their own webhooks, so events are naturally isolated — no tagging needed.
Deliverability & migration
Sender reputation is tied to the sending account and its domains. Under Option A all tenants share one reputation; under Option B each is independent. Either way, every new tenant domain should follow a warm-up schedule and ideally send from a subdomain to protect the tenant’s root domain.
See Create domain, Create API key, and Webhooks for the underlying endpoints.