API Reference

REST API Reference

Complete documentation for every MailSetu endpoint. Base URL: https://maitsetu-production.up.railway.app//v1

Authorization: Bearerms_live_your_api_key

Authentication

All API requests require an API key in the Authorization header.

GEThttps://maitsetu-production.up.railway.app//v1/keysList API keys

Returns all API keys for the authenticated account.

Response
{
  "keys": [
    {
      "id": "key_01HXYZ",
      "name": "Production",
      "keyMask": "ms_live_ab12…cd34",
      "isLive": true,
      "createdAt": "2024-01-15T10:30:00Z"
    }
  ]
}
POSThttps://maitsetu-production.up.railway.app//v1/keysCreate API key

Create a new API key. The full key is returned once — store it securely.

Request body
{
  "name": "Production",
  "isLive": true
}
Response
{
  "id": "key_01HXYZ",
  "name": "Production",
  "key": "ms_live_ab12cd34ef56gh78",
  "isLive": true,
  "createdAt": "2024-01-15T10:30:00Z"
}
DELETEhttps://maitsetu-production.up.railway.app//v1/keys/:idDelete API key

Permanently deletes an API key. All requests using this key will fail immediately.

Response
{ "deleted": true }

Emails

Send transactional emails, retrieve logs, and cancel scheduled sends.

POSThttps://maitsetu-production.up.railway.app//v1/emailsSend email

Send a transactional email. Supports HTML, plain text, attachments, and scheduling.

Request body
{
  "from": "hello@yourdomain.com",
  "to": ["user@example.com"],
  "subject": "Welcome to our app!",
  "html": "<h1>Hello!</h1><p>Welcome aboard.</p>",
  "text": "Hello! Welcome aboard.",
  "reply_to": "support@yourdomain.com",
  "cc": ["manager@example.com"],
  "bcc": ["archive@example.com"],
  "headers": {
    "X-Entity-Ref-ID": "order_123"
  },
  "tags": [
    { "name": "category", "value": "welcome" }
  ],
  "scheduled_at": "2024-02-01T09:00:00Z"
}
Response
{
  "id": "em_01HXYZ",
  "from": "hello@yourdomain.com",
  "to": ["user@example.com"],
  "subject": "Welcome to our app!",
  "status": "QUEUED",
  "createdAt": "2024-01-15T10:30:00Z"
}
POSThttps://maitsetu-production.up.railway.app//v1/emails/batchBatch send

Send up to 100 emails in a single API call. Each email is independent.

Request body
{
  "emails": [
    {
      "from": "hello@yourdomain.com",
      "to": ["alice@example.com"],
      "subject": "Your invoice #1001",
      "html": "<p>Your invoice is ready.</p>"
    },
    {
      "from": "hello@yourdomain.com",
      "to": ["bob@example.com"],
      "subject": "Your invoice #1002",
      "html": "<p>Your invoice is ready.</p>"
    }
  ]
}
Response
{
  "data": [
    { "id": "em_01HABC", "status": "QUEUED" },
    { "id": "em_01HDEF", "status": "QUEUED" }
  ]
}
GEThttps://maitsetu-production.up.railway.app//v1/emailsList emails

Retrieve paginated email logs. Supports filtering by status, date range, and recipient.

Query parameters
limitnumberNumber of results (max 100, default 20)
offsetnumberPagination offset
statusstringFilter by status: QUEUED, SENDING, DELIVERED, FAILED, BOUNCED
from_datestringISO 8601 date — filter emails sent after this date
to_datestringISO 8601 date — filter emails sent before this date
Response
{
  "data": [
    {
      "id": "em_01HXYZ",
      "from": "hello@yourdomain.com",
      "to": ["user@example.com"],
      "subject": "Welcome!",
      "status": "DELIVERED",
      "opens": 2,
      "clicks": 1,
      "createdAt": "2024-01-15T10:30:00Z",
      "deliveredAt": "2024-01-15T10:30:03Z"
    }
  ],
  "total": 142,
  "limit": 20,
  "offset": 0
}
GEThttps://maitsetu-production.up.railway.app//v1/emails/:idGet email

Retrieve full details for a single email including all events.

Response
{
  "id": "em_01HXYZ",
  "from": "hello@yourdomain.com",
  "to": ["user@example.com"],
  "subject": "Welcome!",
  "html": "<h1>Hello!</h1>",
  "status": "DELIVERED",
  "opens": 2,
  "clicks": 1,
  "events": [
    { "type": "sent",      "timestamp": "2024-01-15T10:30:01Z" },
    { "type": "delivered", "timestamp": "2024-01-15T10:30:03Z" },
    { "type": "opened",    "timestamp": "2024-01-15T11:05:22Z" }
  ],
  "createdAt": "2024-01-15T10:30:00Z"
}
POSThttps://maitsetu-production.up.railway.app//v1/emails/:id/cancelCancel scheduled email

Cancel an email that has not yet been sent. Only works while status is SCHEDULED.

Response
{ "id": "em_01HXYZ", "status": "CANCELED" }

SMS

Send OTPs and transactional alerts, inspect delivery logs, and cancel queued SMS.

POSThttps://maitsetu-production.up.railway.app//v1/messagesSend SMS

Queue a transactional or promotional SMS. Recipients must be in E.164 format.

Request body
{
  "channel": "sms",
  "to": "+919876543210",
  "message": "Your MailSetu OTP is 482913. It expires in 10 minutes.",
  "type": "transactional",
  "idempotencyKey": "otp:user_123:login"
}
Response
{
  "id": "sms_01HXYZ",
  "channel": "sms",
  "to": "+919876543210",
  "status": "queued",
  "estimatedSegments": 1,
  "createdAt": "2026-05-06T10:30:00Z"
}
GEThttps://maitsetu-production.up.railway.app//v1/messagesList SMS

Retrieve paginated SMS logs and monthly quota usage.

Response
{
  "data": [
    {
      "id": "sms_01HXYZ",
      "to": "+919876543210",
      "message": "Your OTP is 482913",
      "type": "transactional",
      "status": "delivered",
      "estimatedSegments": 1,
      "createdAt": "2026-05-06T10:30:00Z"
    }
  ],
  "quota": { "used": 120, "limit": 5000, "remaining": 4880 },
  "pagination": { "page": 1, "limit": 50, "total": 1, "pages": 1 }
}
GEThttps://maitsetu-production.up.railway.app//v1/messages/:idGet SMS detail

Inspect a single SMS including its event trail and provider response.

Response
{
  "id": "sms_01HXYZ",
  "to": "+919876543210",
  "message": "Your OTP is 482913",
  "status": "delivered",
  "events": [
    { "type": "sms.queued", "createdAt": "2026-05-06T10:30:00Z" },
    { "type": "sms.sending", "createdAt": "2026-05-06T10:30:01Z" },
    { "type": "sms.delivered", "createdAt": "2026-05-06T10:30:02Z" }
  ]
}
POSThttps://maitsetu-production.up.railway.app//v1/messages/:id/cancelCancel queued SMS

Cancel an SMS that is still queued and has not yet been handed to the provider.

Response
{ "id": "sms_01HXYZ", "status": "canceled" }

Domains

Verify sending domains with DKIM, SPF, and DMARC records.

GEThttps://maitsetu-production.up.railway.app//v1/domainsList domains

List all verified and pending domains on the account.

Response
{
  "data": [
    {
      "id": "dom_01HXYZ",
      "domain": "yourdomain.com",
      "status": "verified",
      "dkim": { "status": "verified", "selector": "mailsetu1" },
      "spf": { "status": "verified" },
      "dmarc": { "status": "pending" },
      "createdAt": "2024-01-10T08:00:00Z"
    }
  ]
}
POSThttps://maitsetu-production.up.railway.app//v1/domainsAdd domain

Add a new domain. Returns DNS records you need to add to verify ownership.

Request body
{ "domain": "yourdomain.com" }
Response
{
  "id": "dom_01HXYZ",
  "domain": "yourdomain.com",
  "status": "pending",
  "dnsRecords": [
    {
      "type": "TXT",
      "name": "mailsetu1._domainkey.yourdomain.com",
      "value": "v=DKIM1; k=rsa; p=MIGfMA0GCS...",
      "purpose": "DKIM"
    },
    {
      "type": "TXT",
      "name": "yourdomain.com",
      "value": "v=spf1 include:spf.mailssetu.in ~all",
      "purpose": "SPF"
    }
  ]
}
POSThttps://maitsetu-production.up.railway.app//v1/domains/:id/verifyVerify domain

Re-check DNS records and update verification status.

Response
{
  "id": "dom_01HXYZ",
  "domain": "yourdomain.com",
  "status": "verified",
  "dkim": { "status": "verified" },
  "spf": { "status": "verified" }
}
DELETEhttps://maitsetu-production.up.railway.app//v1/domains/:idDelete domain

Remove a domain from the account.

Response
{ "deleted": true }

Templates

Store reusable email templates with variable substitution.

GEThttps://maitsetu-production.up.railway.app//v1/templatesList templates

List all saved email templates.

Response
{
  "data": [
    {
      "id": "tpl_01HXYZ",
      "name": "welcome",
      "subject": "Welcome to {{app_name}}",
      "createdAt": "2024-01-10T08:00:00Z"
    }
  ]
}
POSThttps://maitsetu-production.up.railway.app//v1/templatesCreate template

Create a reusable HTML template. Use {{variable}} syntax for dynamic content.

Request body
{
  "name": "welcome",
  "subject": "Welcome to {{app_name}}, {{first_name}}!",
  "html": "<h1>Hi {{first_name}},</h1><p>Welcome to {{app_name}}!</p>",
  "text": "Hi {{first_name}}, welcome to {{app_name}}!"
}
Response
{
  "id": "tpl_01HXYZ",
  "name": "welcome",
  "subject": "Welcome to {{app_name}}, {{first_name}}!",
  "createdAt": "2024-01-15T10:30:00Z"
}
POSThttps://maitsetu-production.up.railway.app//v1/emailsSend with template

Send an email using a saved template. Pass variables in the `data` object.

Request body
{
  "from": "hello@yourdomain.com",
  "to": ["user@example.com"],
  "template_id": "tpl_01HXYZ",
  "data": {
    "first_name": "Priya",
    "app_name": "MyApp"
  }
}
Response
{ "id": "em_01HABC", "status": "QUEUED" }

Webhooks

Subscribe to real-time email delivery and engagement events.

GEThttps://maitsetu-production.up.railway.app//v1/webhook-endpointsList webhooks

List all webhook endpoints configured on the account.

Response
{
  "data": [
    {
      "id": "wh_01HXYZ",
      "name": "Production webhook",
      "url": "https://yourapp.com/webhooks/mailsetu",
      "subscribedEvents": ["email.delivered", "email.bounce", "email.open"],
      "active": true,
      "secretPreview": "whsec_ab12…",
      "createdAt": "2024-01-10T08:00:00Z"
    }
  ]
}
GEThttps://maitsetu-production.up.railway.app//v1/webhook-endpoints/eventsList supported events

Returns all event types you can subscribe to.

Response
{
  "events": [
    "email.queued", "email.scheduled", "email.sending",
    "email.delivered", "email.open", "email.click",
    "email.bounce", "email.complaint", "email.failed", "email.canceled"
  ]
}
POSThttps://maitsetu-production.up.railway.app//v1/webhook-endpointsCreate webhook

Register a new webhook endpoint. We send a signed POST request for each subscribed event.

Request body
{
  "name": "Production webhook",
  "url": "https://yourapp.com/webhooks/mailsetu",
  "subscribedEvents": [
    "email.delivered",
    "email.bounce",
    "email.open",
    "email.click",
    "email.complaint"
  ]
}
Response
{
  "id": "wh_01HXYZ",
  "name": "Production webhook",
  "url": "https://yourapp.com/webhooks/mailsetu",
  "subscribedEvents": ["email.delivered", "email.bounce"],
  "active": true,
  "secretPreview": "whsec_ab12…"
}
PATCHhttps://maitsetu-production.up.railway.app//v1/webhook-endpoints/:idUpdate webhook

Update an existing webhook endpoint URL, name, or subscribed events.

Request body
{
  "subscribedEvents": ["email.delivered", "email.bounce", "email.complaint"]
}
Response
{ "id": "wh_01HXYZ", "active": true, "subscribedEvents": [...] }
POSThttps://maitsetu-production.up.railway.app//v1/webhook-endpoints/:id/rotate-secretRotate webhook secret

Issue a new signing secret. All subsequent payloads use the new secret.

Response
{ "secretPreview": "whsec_newAB12…" }
DELETEhttps://maitsetu-production.up.railway.app//v1/webhook-endpoints/:idDelete webhook

Remove a webhook endpoint. No further events will be delivered.

Response
{ "deleted": true }

Suppressions

Manage unsubscribes, bounces, and spam complaints.

GEThttps://maitsetu-production.up.railway.app//v1/suppressionsList suppressions

List all suppressed email addresses.

Query parameters
reasonstringFilter by reason: bounce, complaint, unsubscribe
limitnumberMax 100
offsetnumberPagination offset
Response
{
  "data": [
    {
      "email": "user@example.com",
      "reason": "bounce",
      "createdAt": "2024-01-15T10:30:00Z"
    }
  ],
  "total": 12
}
POSThttps://maitsetu-production.up.railway.app//v1/suppressionsAdd suppression

Manually add an email address to the suppression list.

Request body
{
  "email": "user@example.com",
  "reason": "unsubscribe"
}
Response
{ "added": true }
DELETEhttps://maitsetu-production.up.railway.app//v1/suppressions/:emailRemove suppression

Remove an email address from the suppression list.

Response
{ "removed": true }

Error codes

All errors follow a consistent shape: { "error": "CODE", "message": "Human-readable text" }

StatusCodeDescription
400BAD_REQUESTMissing or invalid request parameters.
401UNAUTHORIZEDMissing or invalid API key.
403FORBIDDENThis key does not have permission for this action.
404NOT_FOUNDThe requested resource does not exist.
422VALIDATION_ERRORRequest body failed validation. Check the `errors` field.
429RATE_LIMITEDToo many requests. Respect the Retry-After header.
500INTERNAL_ERRORSomething went wrong on our side. Retry with exponential backoff.
503PAYMENT_REQUIREDRazorpay credentials not configured — contact support.
Rate limits
Free: 100 req/min  ·  Starter: 500 req/min  ·  Growth: 2000 req/min
Exceeded? You'll receive a 429 — use the Retry-After header.
Quickstart guide