Skip to content
Moosewave
Demo

Transactional email API · design preview

Product email your app can retry without sending twice.

See how Moosewave is designing one API for password resets, receipts, account alerts, and other product email, with recipient checks and a result your application can inspect.

This page is a product design preview. The public website does not issue API credentials or link to production documentation or installable SDKs today. Endpoint shapes and limits below may change before public access.

One plain example

A password-reset request times out.

  1. Your app asks for one reset emailIt includes a stable request key.
  2. The response does not arriveYour app cannot tell whether the provider received it.
  3. Your app repeats the same requestIt uses the same key and unchanged content.
  4. The existing message record comes backThe design does not create a second email.
This illustrates the intended behavior. It is not a live API response.

Follow the design

Start with one password-reset email.

Change the example or code language if you want more detail. Then repeat the request to see why the stable key matters. Every value and response below is illustrative.

Choose a product eventExplore the proposed request and result. No live endpoint is called.
Proposed: POST /api/v1/emailsIllustrative request
curl --request POST \  "$MOOSEWAVE_API_BASE/api/v1/emails" \  --header "Authorization: Bearer $MOOSEWAVE_API_KEY" \  --header "Idempotency-Key: reset_user_42_attempt_1" \  --header "Content-Type: application/json" \  --data '{    "from": "Moosewave <mail@example.com>",    "to": "ada@example.com",    "subject": "Reset your password",    "html": "<p>Use this link to reset your password.</p>",    "tags": [{ "name": "event", "value": "account.password_reset_requested" }]  }'
Protect an accountaccount.password_reset_requestedExample · 202 accepted

In this design, one account event becomes one traceable send. A retry keeps the same request key instead of creating a second password-reset email.

  1. Intent claimedThe key is attached before the provider call.

  2. Sender verifiedThe From domain belongs to this workspace.

  3. Recipients checkedConfigured do-not-contact rules are checked.

  4. Outcome recordedThe provider response stays with the message ID.

Illustrative responseExample message record
{
  "id": "eml_reset_7f31",
  "status": "sent",
  "suppressed": 0
}

The design keeps the provider result attached to this message ID. The “suppressed” count is 0 because no recipient was held back by a do-not-contact rule.

Stable request key
Interactive design preview. Choose an event and language, then repeat the request. This example does not call a live endpoint.

One person, one service event

What is transactional email?

Transactional email is a one-to-one message sent because a person used a product or because an account changed. It completes, confirms, or protects that interaction: a verification link, password reset, receipt, shipping update, billing notice, or security alert.

It is not marketing email with a different label. Purpose, audience, content, and applicable consent rules still matter. Use marketing automation when an audience rule or journey owns the send.

Scroll horizontally to compare both message types.
QuestionTransactionalMarketing
What starts it?A user action, account event, or service obligation.A campaign, schedule, or audience rule.
Who receives it?The person involved in that event.A selected audience or segment.
What is its job?Complete, confirm, or protect a service interaction.Promote, educate, or nurture.
A familiar exampleA password-reset link or purchase receipt.A product-news or re-engagement campaign.

The useful part

One request. Three questions answered.

Before sending

Is the request allowed, is the sending domain verified, and should this person receive it?

When retrying

Is this the same email request or a genuinely new one?

After handoff

What did Moosewave know, what did the provider report, and what is still unknown?

Developer detail

Open only what you need.

These are proposed API shapes and safeguards, included so product and engineering teams can evaluate the design. They are not public production documentation.

Request shape and proposed routesContent, recipients, attachments, scheduling, routes, and intended client coverage.

Address the real conversation

The proposed request supports from, to, cc, bcc, and reply_to. The current design cap is 50 total recipients across to, cc, and bcc.

Send readable content

The request shape accepts HTML, plain text, or both, together with a subject and a sender verified for the workspace.

Carry application context

Custom headers and per-message key/value tags keep a product event identifiable downstream.

Attach the useful thing

The design includes base64 attachments and inline files referenced by content ID. The current design cap is 25 MiB decoded per message.

Choose when it should leave

A request can be immediate or include a future RFC 3339 scheduled_at time. Scheduled work remains attached to the same message record.

Keep batches transactional

The proposed batch shape contains distinct messages and returns one outcome for each item. A batch is not an audience campaign.

Proposed REST routes

Paths, permissions, and limits may change before public API access.

Scroll horizontally to read every proposed route.
MethodPathPurposePermission
POST/api/v1/emailsProposed route for sending or scheduling one transactional email.send:transactional
POST/api/v1/emails/batchProposed batch route, with one result for each distinct message.send:transactional
GET/api/v1/emails/{id}Proposed route for reading the current record for one message.read:reports
GET/api/v1/emailsProposed route for listing recent sends by attempt status.read:reports

Intended client-language coverage

No installable SDK packages are linked on this website today.

  • TypeScript
  • Python
  • PHP
  • Go
  • Java
  • .NET
  • Ruby
  • Rust
  • Elixir
Safer retries and honest statusWhy a stable request key matters, and why API acceptance is not inbox delivery.

The same request should not send twice.

The application gives an email a stable request key. If a response gets lost, it can repeat the unchanged request and get the existing record back. Developers call this idempotency; the plain meaning is simply “do not repeat the send.”

Same key, same email

Return the existing record

The application can retry without asking the provider to create another email.

Same key, changed email

Return a conflict

Changed content is not treated as the original request.

No request key

Treat it as new

The application decides which requests belong together.

A request result is not an inbox result.

  1. API accepted

    The request passed API validation.

  2. Provider accepted

    The delivery provider accepted the handoff.

  3. Mailbox received

    The receiving system accepted responsibility for the message.

  4. Placement observed

    The message appeared in inbox, promotions, spam, or elsewhere.

Proposed message states

Prepared

The design records the request before any provider call is known.

prepared
Submitted

The provider accepted the handoff and returned a reference when available.

submitted
Rejected

The provider refused the attempt, so the record can say it did not leave.

rejected
Unknown

The connection ended without enough information to know whether the provider accepted it. The design stops rather than guessing or resending automatically.

unknown

Learn how those results differ in email deliverability and email analytics.

Access checks and suitable messagesWhat the design checks and which customer events belong here.

Request permission

A sending service gets only the access its job needs.

Workspace

The request and result stay attached to the correct workspace.

Sending domain

The From domain must be verified for that workspace.

Recipients

Configured do-not-contact rules are checked before provider handoff.

See the current public description of Moosewave security.

Common transactional email examples

Account verification

Confirm that the address belongs to the person creating the account.

Password reset and sign-in

Deliver a time-bound path back into an account without turning it into a campaign.

Receipts and invoices

Give a customer a durable record of a purchase, payment, or subscription change.

Order and shipping updates

Explain what changed after checkout and what the customer should expect next.

Security alerts

Describe a new device, sensitive change, or recovery action while the event is still relevant.

Invitations and roles

Tell a person who invited them, what access changed, and where to continue.

Billing notices

Connect renewals, failed payments, refunds, and plan changes to the account event that caused them.

Product notifications

Send the one-to-one update a user asked the application to produce.

Transactional email API, answered plainly.

The first answer explains what is, and is not, available from this website today.

Can I get a Moosewave transactional email API key today?

Not from this public website. This page is an API design preview: it explains the intended request flow, endpoint shape, safeguards, and status model. Public credentials, production documentation, and installable SDK packages are not linked here today.

What is a transactional email API?

A transactional email API lets an application send one-to-one messages in response to user actions or account events. Common examples include verification links, password resets, receipts, order updates, billing notices, and security alerts.

What is the difference between transactional and marketing email?

Transactional email completes, confirms, or protects an existing service interaction. Marketing email promotes, educates, or nurtures an audience. The message’s real purpose and content determine the category; changing its label does not change its obligations.

Which SDKs are available for the transactional email API?

No public SDK packages are linked on this website today. The design targets ordinary REST clients and shows intended language coverage for TypeScript, Python, PHP, Go, Java, .NET, Ruby, Rust, and Elixir. Those names describe the planned client surface, not a download promise.

How does Moosewave prevent duplicate email during retries?

Developers call this idempotency; here it simply means that the same request should not send twice. The design gives each email one stable request key. Repeating the same content with the same key returns the original message record; using that key for different content returns an error. Without a key, each request is treated as new.

What happens if the provider times out during a send?

The proposed status model records an unclear provider result as unknown and does not automatically resend it. That avoids turning an uncertain network result into a duplicate while keeping the case visible for review.

Does Moosewave check do-not-contact rules for transactional email?

Yes. The design checks configured do-not-contact rules, often called suppressions in email systems, before dispatch. People covered by those rules are left out of the provider request, and the message record reports how many were withheld instead of presenting them as sent.

Can I schedule or batch transactional email?

The current design includes a future scheduled_at value for one message and a proposed batch route that returns one result per item. These are previewed request shapes, not publicly documented production endpoints. A batch remains transactional work; it is not a substitute for an audience campaign.

Can transactional emails include attachments?

The current design includes base64 attachments and inline files referenced with a content ID, with a proposed decoded total of 25 MiB per message. That limit may change before public API access.

Can I build personalized transactional email templates?

The API design accepts final HTML and does not depend on a hosted template ID. A product can render customer-specific values in its own template system and submit the result. Public API credentials and production documentation are not available from this website today.

Does a successful API response mean the email reached the inbox?

No. HTTP acceptance, provider submission, mailbox delivery, and inbox placement are different results. The Moosewave design keeps those stages separate so a successful request is not presented as proof that the recipient saw the message.

Do I need to verify my sending domain?

The design requires the From domain to belong to the requesting workspace before dispatch. This prevents one workspace from using another workspace’s sending identity and gives SPF, DKIM, and DMARC a valid foundation.

See it in context

Follow the whole customer journey.

The guided demo uses sample data, requires no signup, and sends no email. You can also review the planned integration paths.