Skip to main content
POST
/
public
/
v1
/
emails
curl --request POST \
  --url https://api.minimo.it/public/v1/emails \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "to": "customer@example.com",
  "subject": "Your receipt",
  "html": "<p>Thanks for your purchase. <a href=\"https://example.com/receipt/12345\">View receipt</a></p>"
}
'
{
  "data": {
    "id": "DMPNEF8",
    "status": "sent",
    "messageId": "0100019c8b3d4a4f-...",
    "statsUrl": "/public/v1/emails/DMPNEF8/stats"
  }
}

Documentation Index

Fetch the complete documentation index at: https://docs.minimo.it/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Use this endpoint when you want to send a transactional email without creating a template in the dashboard. You provide the rendered HTML yourself and Minimo handles dispatch, delivery, and tracking. Typical use cases:
  • Server-side rendered receipts: invoices, order confirmations, shipping notifications
  • Authentication flows: magic links, OTP delivery, email verification
  • Internal notifications: alerts produced by your own background jobs
  • Anything dynamic enough to not fit a pre-defined template
Tracking (open pixel + click rewriting) is injected server-side. Send your raw HTML as-is — don’t pre-rewrite links or append a pixel yourself.

Before You Start

  1. Generate an API key with the TRANSACTIONAL permission from the Minimo dashboard.
  2. Make sure your company’s email provider is configured (SMTP or SES).
  3. Have your HTML body ready — Minimo doesn’t render templates for this endpoint.

What the Server Does to Your HTML

When you send html, the backend:
  1. Resolves placeholders: {{UNSUBSCRIBE_URL}}, {{PREFERENCES_URL}}, and {{FAKE_IMAGE_URL}} are replaced with the per-recipient tracked URLs.
  2. Strips any pre-existing tracking pixel: an <img> whose src matches the Minimo open-pixel pattern is removed so it can’t double-fire.
  3. Rewrites tracked anchors: every <a href> pointing to http(s) or a relative URL is replaced with a click-tracking URL. mailto:, fragment-only (#…), and pre-existing /api/click/* links are left alone.
  4. Appends the open-tracking pixel at the end of <body> (or at the document root if no <body> exists).
The recipient receives the final HTML; analytics flow into GET /public/v1/emails/{id}/stats.

Example Request

curl --request POST \
  --url https://api.minimo.it/public/v1/emails \
  --header 'Authorization: Bearer mn-{apiClientId}-{secret}' \
  --header 'Content-Type: application/json' \
  --data '{
    "to": "customer@example.com",
    "subject": "Your receipt",
    "html": "<p>Thanks for your purchase. <a href=\"https://example.com/receipt/12345\">View receipt</a></p>"
  }'

Response Shape

The endpoint always returns HTTP 200 when authentication succeeds — inspect status to know whether the provider accepted the message.
{
  "data": {
    "id": "DMPNEF8",
    "status": "sent",
    "messageId": "0100019c8b3d4a4f-...",
    "statsUrl": "/public/v1/emails/DMPNEF8/stats"
  }
}
When the provider rejects the message you still get back the same id, so the delivery row remains queryable:
{
  "data": {
    "id": "DMPNEF8",
    "status": "failed",
    "failureReason": "Email address is not verified.",
    "statsUrl": "/public/v1/emails/DMPNEF8/stats"
  }
}

Use Cases

Plain HTML with a single CTA is enough — the open and click events surface in the stats endpoint.
{
  "to": "ops@example.com",
  "subject": "[ALERT] Queue depth above threshold",
  "html": "<p>Worker queue at 12,400 jobs.</p><p><a href=\"https://admin.example.com/jobs\">Open dashboard</a></p>",
  "text": "Worker queue at 12,400 jobs. Open dashboard: https://admin.example.com/jobs"
}

Best Practices

Pair every send with a statsUrl lookup

The response includes statsUrl. Persist the id (or the full statsUrl) alongside whatever business object triggered the send (order id, user id, etc.) so you can correlate opens and clicks later.

Handle the failed branch

status: "failed" means the provider rejected the message — usually a malformed recipient, an unverified sender, or a hard bounce. Surface failureReason to your operators, then either retry with corrected data or log the failure.

Keep HTML self-contained

Inline your CSS. Many email clients drop <style> blocks. Test in major clients (Gmail, Apple Mail, Outlook) before going live.

Provide a text fallback for deliverability

Spam filters reward multipart messages. Adding a plain-text alternative reduces the chance of landing in the junk folder.

Don’t double-track

If your HTML already contains /api/click/* URLs or an open pixel from a previous Minimo send, leave them alone — the server detects and skips them. Inserting your own tracking on top is unnecessary.

Common Errors

StatusBodyCause
400{ "error": "to must be an email" }Invalid or missing required field
401API key missing or wrong format
403API key lacks the TRANSACTIONAL permission
200{ "data": { "status": "failed", "failureReason" } }Provider rejected the message (still a 200)
500Server misconfiguration (e.g. WEB_APP_URL unset)

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

application/json
to
string<email>
required

Recipient email address.

subject
string
required

Email subject line.

html
string
required

Pre-rendered HTML body. The server injects the open pixel and rewrites anchor hrefs — do not pre-process them on your side.

text
string

Plain-text fallback for clients without HTML support.

fromAddress
string<email>

Per-request sender override. Falls back to the company email settings.

fromName
string

Per-request sender display name override.

Response

Delivery accepted by the queue. Check data.status to tell whether the provider actually accepted the message.

data
object