Skip to content
MIRNINTMail

Developers

A small API surface you can trust

Everything speaks JSON over HTTPS at https://api.mail.mirnint.com/v1, documented with OpenAPI 3.1. Accepted means durably stored — delivery truth arrives as events.

Endpoints

The surface area

MethodPathPurpose
POST/v1/emailsSend an email or a template send — returns 202 once durably stored
GET/v1/emails/{id}Message metadata, per-recipient states and derived status
GET/v1/emails/{id}/eventsCursor-paginated lifecycle events
POST/v1/emails/{id}/cancelCancel a scheduled message before MTA submission
POST/v1/contact-submissionsRestricted contact-form intake with server-side routing

Authentication is a project-scoped bearer key (mm_live_… / mm_test_…). Test keys can only send to approved recipients.

Webhooks

Events you can verify

Every webhook is HMAC-SHA-256 signed over the webhook ID, timestamp and raw body. Reject stale timestamps, deduplicate by event ID, and you're immune to replay.

  • email.accepted
  • email.queued
  • recipient.submitted_to_mta
  • recipient.deferred
  • recipient.remote_accepted
  • recipient.soft_bounced
  • recipient.hard_bounced
  • recipient.complained
  • recipient.suppressed
  • email.completed
webhook-verify.ts
// Verify a webhook before trusting it
const canonical = [
  req.headers["mirnint-webhook-id"],
  req.headers["mirnint-webhook-timestamp"],
  rawBody,
].join(".");

const expected = "v1=" + hmacSha256(secret, canonical);

if (!timingSafeEqual(expected,
    req.headers["mirnint-webhook-signature"])) {
  return res.status(401).end();
}
// Reject stale timestamps, dedupe by event id
handle(JSON.parse(rawBody));
// { "type": "recipient.remote_accepted", ... }

Error handling

Failures are part of the contract

Stable error codes, request IDs on every response, and idempotency that makes retries safe. Ambiguity is designed out: an SDK never blindly re-sends after a timeout without the same idempotency key.

SDKs

TypeScript · Java · PHP · Python — generated from the OpenAPI spec with typed errors and sensible timeouts.

Rate-limit headers

Documented headers on every response, with independent limits per key, project and organization.

Content limits

Explicit maximum body and attachment sizes, enforced before queueing — including Base64 expansion.

Error envelope
HTTP/1.1 422 Unprocessable Entity
{
  "error": {
    "code": "DOMAIN_NOT_VERIFIED",
    "message": "The selected sending domain
                is not verified.",
    "request_id": "req_01J9X4M2",
    "details": { "domain_id": "dom_01J9X4" }
  }
}