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.
- Your app asks for one reset emailIt includes a stable request key.
- The response does not arriveYour app cannot tell whether the provider received it.
- Your app repeats the same requestIt uses the same key and unchanged content.
- The existing message record comes backThe design does not create a second email.
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.
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" }] }'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.
Intent claimedThe key is attached before the provider call.
01Sender verifiedThe From domain belongs to this workspace.
02Recipients checkedConfigured do-not-contact rules are checked.
03Outcome recordedThe provider response stays with the message ID.
04
{
"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.
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.
| Question | Transactional | Marketing |
|---|---|---|
| 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 example | A 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.
| Method | Path | Purpose | Permission |
|---|---|---|---|
| POST | /api/v1/emails | Proposed route for sending or scheduling one transactional email. | send:transactional |
| POST | /api/v1/emails/batch | Proposed 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/emails | Proposed 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 emailReturn the existing record
The application can retry without asking the provider to create another email.
Same key, changed emailReturn a conflict
Changed content is not treated as the original request.
No request keyTreat it as new
The application decides which requests belong together.
A request result is not an inbox result.
- API accepted
The request passed API validation.
- Provider accepted
The delivery provider accepted the handoff.
- Mailbox received
The receiving system accepted responsibility for the message.
- Placement observed
The message appeared in inbox, promotions, spam, or elsewhere.
Proposed message states
The design records the request before any provider call is known.
preparedThe provider accepted the handoff and returned a reference when available.
submittedThe provider refused the attempt, so the record can say it did not leave.
rejectedThe connection ended without enough information to know whether the provider accepted it. The design stops rather than guessing or resending automatically.
unknownLearn 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.
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.