Skip to main content

Mailroom

Mailroom is a multi-tenant email platform: first-party contacts, template rendering, transactional and marketing sends, lifecycle sequences, and campaigns — exposed as an HTTP API (/api/v1) with a typed TypeScript client, @mailroom/sdk.

Your product calls Mailroom; Mailroom owns the list, the rendering, the sending, the suppressions, and the engagement data.

const { id } = await mailroom.send({
to: "ada@example.com",
template: "welcome",
data: { name: "Ada" },
});

Start with the Quickstart →

Server-to-server only

An API key (pk_live_…) is a secret with full project access. It belongs on a server, in a worker, or in a build step — never in a browser bundle, a mobile app, or anything a user can read. There is no public/publishable key variant and no CORS story: Mailroom is not designed to be called from client code.

See Authentication.

How the pieces fit

ConceptWhat it is
ContactA person on your list, unique per project by email, with status, tags, and consent metadata.
TemplateCode-defined email in the registry, enabled per project, rendered with data you pass at send time.
SendOne email attempt. Logged with delivery and engagement state as webhooks land.
CampaignOne-off send to an audience (everyone, a tag, a segment, or an explicit list), optionally scheduled and A/B split.
SequenceA flow graph (trigger → wait → send → branch) that contacts move through as enrollments.
SegmentA saved audience filter, evaluated at send time.
SuppressionAn address Mailroom will not send to (bounce, complaint, or manual).
WebhookYour endpoint, receiving signed events (email.bounced, contact.unsubscribed, …).

Tenancy: Org → Project → Brand

Every row in Mailroom is scoped by project. A project owns its contacts, API keys, sending domains, templates, and unsubscribe secret — two projects never see each other's data.

A brand is a sending identity inside a project (from-address, theme). Most integrations use one brand and can ignore the parameter; multi-brand setups pass brand per call or set defaultBrand on the client.

An org groups projects for billing and team access. It never appears in the API surface: your key already resolves to exactly one project.

The SDK versus raw HTTP

The SDK is a thin, dependency-free wrapper: one method per endpoint, resolving to the response data and throwing typed errors. It adds retries with jittered backoff, automatic idempotency keys on mutations, cursor pagination helpers, and webhook signature verification — all of which you would otherwise write yourself.

If you are not on TypeScript or JavaScript, call the REST API directly; the endpoint reference documents the same surface, including the scopes each route requires.