Transactional email API
Transactional email that keeps its receipts.
Send password resets, receipts, account alerts, and product notifications through one API. Every request gets a traceable identity, sender and recipient checks, and an honest provider outcome—including unknown when the network cannot prove what happened.
- REST + nine SDKs
- Use the client your application already speaks
- Replay-safe requests
- A stable key resolves duplicate retries
- Queryable outcomes
- Read the message record after the response
POST /api/v1/emails- To
- ada@example.com
- Intent
- reset_user_42_attempt_1
- 01Intent Claimed
- 02Sender Verified
- 03Recipients Checked
eml_reset_7f31One 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, invitation, 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 a journey or audience rule—not one application event—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 message flight recorder
How does the transactional email API work?
Your application posts the message and a stable request identity. Moosewave validates the request, records the intent before provider dispatch, and keeps the resulting evidence on one message record that your application can read later.
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" }] }'One account event becomes one traceable send. A retry keeps the same intent key instead of inventing a second password-reset email.
Intent claimedThe key is attached before the provider call.
01Sender verifiedThe From domain belongs to this workspace.
02Recipients checkedConfigured suppressions are evaluated.
03Outcome recordedProvider evidence stays with the message ID.
04
{
"id": "eml_reset_7f31",
"status": "sent",
"suppressed": 0
}The provider handoff and its receipt remain attached to this Moosewave message ID.
- 01
Name the intent
Your application gives the logical message a stable Idempotency-Key before it makes the request.
- 02
Validate the request
Moosewave checks the payload, the key scope, the workspace, and the verified From domain.
- 03
Check recipients
Configured suppressions are evaluated and the number withheld is written to the message record.
- 04
Submit or schedule
The message is handed to the provider now or held for a future dispatch time. Batch items keep separate outcomes.
- 05
Keep the receipt
The message ID, provider result, attempt state, suppression count, and timestamps remain queryable together.
Useful without becoming unbounded
What can the email API send?
The API covers the pieces application email actually needs: addressed HTML and text, reply paths, context, attachments, scheduling, and distinct batch messages. Limits are explicit so an integration can fail predictably before an accidental payload becomes an operational surprise.
Address the real conversation
Use from, to, cc, bcc, and reply_to. One message may contain up to 50 total recipients across to, cc, and bcc.
Send readable content
Provide HTML, plain text, or both, together with a subject and the sender your workspace has verified.
Carry application context
Add custom headers and per-message key/value tags so one product event remains identifiable downstream.
Attach the useful thing
Include base64 attachments and inline files referenced by content ID, up to 25 MiB decoded across the message.
Choose when it should leave
Send immediately or provide a future RFC 3339 scheduled_at time. Scheduled work remains attached to the same message record.
Keep batches transactional
Submit up to 100 distinct messages in one batch and receive an individual outcome for every position. A batch is not an audience campaign.
Build personalized templates in React and MJML.
Start with 15 props-driven email patterns, supply customer-specific values in your application, render the final HTML, and send it through the API. No hosted template ID is required.
See the developer ecosystemA small surface with clear jobs
Four endpoints cover send, batch, and status history.
Write calls require the send:transactional scope. Reading message records requires read:reports. Give each service only the access its job needs.
Client libraries
- TypeScript
- Python
- PHP
- Go
- Java
- .NET
- Ruby
- Rust
- Elixir
Use a client library or call the REST endpoints with your existing HTTP client.
| Method | Path | Purpose | Scope |
|---|---|---|---|
| POST | /api/v1/emails | Send or schedule one transactional email. | send:transactional |
| POST | /api/v1/emails/batch | Send up to 100 distinct transactional messages with one result per item. | send:transactional |
| GET | /api/v1/emails/{id} | Read the current record for one message identity. | read:reports |
| GET | /api/v1/emails | List recent sends and narrow the ledger by attempt state. | read:reports |
Retry the request, not the consequence
How does Moosewave prevent duplicate transactional email?
Give one logical email one stable Idempotency-Key. Moosewave claims that intent before provider dispatch and compares later requests with the original content. The result is idempotent API submission with explicit visibility when a provider outcome is ambiguous—not an impossible promise that networks deliver exactly once.
same key + same content01Return the original result
A network retry resolves to the recorded message identity. A completed intent does not make a second provider call.
Replay-safe
same key + changed content02Refuse the ambiguity
Moosewave returns a conflict instead of silently treating a different message as the first one.
409 conflict
no idempotency key03Treat it as a new send
Each unkeyed request is deliberate new work. The API does not invent business identity on your application’s behalf.
New intent
provider outcome unclear04Say unknown and stop
When transport ends without decisive evidence, the attempt stays visible for review and is not blindly resent.
Human review
A 202 is the beginning of the record
Does API success mean the email was delivered?
No. HTTP acceptance means Moosewave accepted a valid request. A provider receipt means the delivery provider accepted the handoff. Mailbox delivery and inbox placement happen later and are different facts. The API record keeps these boundaries visible instead of turning “sent” into proof that someone received or saw the message.
- 01
API accepted
The request passed API validation and has a Moosewave response.
- 02
Provider accepted
The sending provider returned a receipt for the handoff.
- 03
Mailbox received
The receiving system accepted responsibility for the message.
- 04
Placement observed
The message surfaced in inbox, promotions, spam, or elsewhere.
Transport evidence and inbox evidence answer different questions.
Use the API record to inspect submission. Use deliverability evidence to understand authentication, mailbox acceptance, and placement.
Explore deliverabilityThe ledger remembers uncertainty
What can you inspect after sending?
Get one message by ID or list recent messages, including a filter for ambiguous attempts. Each record can expose its source, recipients, subject, schedule, status, provider message ID, suppression count, timestamps, last error, attempt state, and whether an external effect may have occurred.
- 01PreparedMoosewave recorded the intent; no provider call is known yet.
prepared - 02SubmittedThe provider accepted the handoff and returned a receipt when available.
submitted - 03RejectedThe provider definitely refused the attempt, so the record can say it did not leave.
rejected - 04UnknownThe connection ended without enough evidence to know whether the provider accepted it. Moosewave does not guess or resend automatically.
unknown
Before provider dispatch
What does Moosewave check before sending?
A valid payload is only one part of an authorized send. Moosewave resolves every API key to a workspace, enforces the required scope, checks the From domain against that workspace’s verified identities, and evaluates configured suppressions before preparing the provider request.
Scoped credentials
Give a sending service send:transactional without also giving it reporting or administrative access.
Workspace isolation
Every request and message record belongs to the tenant resolved from the API key.
Verified identities
The From domain must be the platform default or an identity verified for that workspace.
Bounded requests
Recipient, attachment, batch, and body limits keep malformed or runaway work predictable.
Need tighter key controls? API keys can carry granular scopes, optional expiry, HTTP IP allowlists, request limits, and revocation.
See Moosewave securityEvents customers recognize
Which emails belong in a transactional API?
Use the API when your application already knows the person, the event, and why the message must exist. Keep promotional sequences and audience broadcasts in the marketing workspace where consent, frequency, and campaign measurement can be managed as a program.
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.
One product, different entry points
API for application events. MCP for assistant workflows.
Your product backend should use the transactional API when code owns a deterministic event. A compatible assistant can use Moosewave MCP tools to send, retrieve, or list email within its own scoped connection. Both paths preserve workspace authorization and a result your team can inspect.
See where app email meets the customer story.
Follow audiences, messages, approvals, events, and results across the wider Moosewave ecosystem.
Explore the ecosystem MCP & AI toolsGive an assistant a small, typed email job.
Use dedicated connection scopes for email send, get, and list tools without making the assistant a hidden admin.
Explore Moosewave MCPTransactional email API, answered plainly.
What application teams should know before the first production request.
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?
Moosewave provides SDK surfaces for TypeScript, Python, PHP, Go, Java, .NET, Ruby, Rust, and Elixir. Any application can also call the REST API directly with its normal HTTP client.
How does Moosewave prevent duplicate email during retries?
Supply one stable Idempotency-Key for the logical message. A retry with the same key and content returns the original send record; using that key for different content returns a conflict. A request without a key is treated as a deliberate new send.
What happens if the provider times out during a send?
If Moosewave cannot know whether the provider accepted the message, the attempt is recorded as unknown and is not automatically resent. That avoids converting an uncertain network result into a duplicate while keeping the case visible for investigation.
Does Moosewave check suppressions for transactional email?
The transactional send path checks configured suppressions before dispatch. Suppressed recipients are excluded from the provider request, and the message record reports how many recipients were withheld instead of silently presenting them as sent.
Can I schedule or batch transactional email?
Yes. A future scheduled_at value schedules one message, and the batch endpoint accepts up to 100 distinct transactional messages with one result per item. A batch remains transactional work; it is not a substitute for an audience campaign.
Can transactional emails include attachments?
Yes. The API accepts base64 attachments and inline files referenced with a content ID. The decoded attachment total is limited to 25 MiB per message so unexpectedly large requests remain bounded.
Can I build personalized transactional email templates?
Yes. Moosewave includes 15 props-driven React email starters that render through MJML. Your application supplies the customer-specific values, renders the final HTML, and submits that HTML through the API; the send endpoint does not depend on a hosted template ID.
Does a successful API response mean the email reached the inbox?
No. HTTP acceptance, provider submission, mailbox delivery, and inbox placement are different results. Moosewave keeps those stages separate so a successful request is not misreported as proof that the recipient saw the message.
Do I need to verify my sending domain?
Yes. Moosewave verifies that the From domain belongs to the requesting workspace before dispatch. This prevents one tenant from using another tenant’s sending identity and gives SPF, DKIM, and DMARC a valid foundation.
Give important product email an identity and a receipt.
Connect your application, choose the smallest key scope, and keep every provider outcome available to the people who operate the product.
