Skip to content
Early access

Moosewave is in private early access and not yet generally available. Join the waitlist for an invitation.

Moosewave

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
Application eventPOST /api/v1/emails
Password reset requestedReset your password
To
ada@example.com
Intent
reset_user_42_attempt_1
  1. 01Intent Claimed
  2. 02Sender Verified
  3. 03Recipients Checked
Provider receipt recordedOne message identity, ready to inspecteml_reset_7f31
Illustrative values. The real record keeps request identity and provider evidence together.

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, 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.

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 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.

Choose a product eventFollow one request from application intent to recorded outcome.
POST /api/v1/emails Scoped key
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_requested202 accepted

One account event becomes one traceable send. A retry keeps the same intent key instead of inventing 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 suppressions are evaluated.

  4. Outcome recordedProvider evidence stays with the message ID.

Illustrative responseMessage record created
{
  "id": "eml_reset_7f31",
  "status": "sent",
  "suppressed": 0
}

The provider handoff and its receipt remain attached to this Moosewave message ID.

Stable intent key
Choose an event and language, then replay the request to see how one logical send keeps one message identity.
  1. 01

    Name the intent

    Your application gives the logical message a stable Idempotency-Key before it makes the request.

  2. 02

    Validate the request

    Moosewave checks the payload, the key scope, the workspace, and the verified From domain.

  3. 03

    Check recipients

    Configured suppressions are evaluated and the number withheld is written to the message record.

  4. 04

    Submit or schedule

    The message is handed to the provider now or held for a future dispatch time. Batch items keep separate outcomes.

  5. 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 ecosystem

A 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.

Scroll horizontally to read every endpoint.
MethodPathPurposeScope
POST/api/v1/emailsSend or schedule one transactional email.send:transactional
POST/api/v1/emails/batchSend 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/emailsList 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 content01

Return 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 content02

Refuse the ambiguity

Moosewave returns a conflict instead of silently treating a different message as the first one.

409 conflict

no idempotency key03

Treat 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 unclear04

Say 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.

  1. 01

    API accepted

    The request passed API validation and has a Moosewave response.

  2. 02

    Provider accepted

    The sending provider returned a receipt for the handoff.

  3. 03

    Mailbox received

    The receiving system accepted responsibility for the message.

  4. 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 deliverability

The 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.

  1. 01PreparedMoosewave recorded the intent; no provider call is known yet.prepared
  2. 02SubmittedThe provider accepted the handoff and returned a receipt when available.submitted
  3. 03RejectedThe provider definitely refused the attempt, so the record can say it did not leave.rejected
  4. 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.

Checked before dispatch

Scoped credentials

Give a sending service send:transactional without also giving it reporting or administrative access.

Checked before dispatch

Workspace isolation

Every request and message record belongs to the tenant resolved from the API key.

Checked before dispatch

Verified identities

The From domain must be the platform default or an identity verified for that workspace.

Checked before dispatch

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 security

Events 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.

01

Account verification

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

02

Password reset and sign-in

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

03

Receipts and invoices

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

04

Order and shipping updates

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

05

Security alerts

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

06

Invitations and roles

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

07

Billing notices

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

08

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.

Transactional 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.

Make every request accountable

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.