Documentation

Email API

The full REST reference. All endpoints are under https://app.mailstein.com/api/v1 and require a bearer API key. For live, schema-complete request builders use the interactive reference ↗.

Conventions

Emails

POST /v1/emails Send an email
POST /v1/emails/batch Send up to a batch of emails in one call
GET /v1/emails List emails
GET /v1/emails/{emailId} Retrieve one email + status
PATCH /v1/emails/{emailId} Reschedule a queued email
POST /v1/emails/{emailId}/cancel Cancel a scheduled email

POST /v1/emails

FieldTypeNotes
from requiredstringSender on a verified domain. Name <you@domain.com> is supported.
to requiredstring | string[]One recipient or an array.
subjectstringOptional when templateId is provided.
htmlstringHTML body.
textstringPlain-text body / fallback.
templateIdstringID of a template from the dashboard.
variablesobjectValues substituted into the template.
replyTostring | string[]Reply-To address(es).
cc / bccstring | string[]Carbon / blind copy.
attachmentsarrayFile attachments (name + base64 content).
headersobjectCustom headers to include on the message.
scheduledAtstringISO-8601 time to send later.
inReplyToIdstringThread a reply to a prior message.
Request
{
  "from": "hello@yourdomain.com",
  "to": "customer@example.com",
  "subject": "Your receipt",
  "html": "<p>Thanks for your order.</p>"
}
200 Response
{ "emailId": "em_8fk2..." }

Domains

GET /v1/domains List domains
POST /v1/domains Add a sending domain
GET /v1/domains/{id} Retrieve a domain + DNS records
PUT /v1/domains/{id}/verify Re-check DNS and verify
DELETE /v1/domains/{id} Remove a domain

See Domains & DNS for the records and verification flow.

Contacts & contact books

GET /v1/contactBooks List contact books
POST /v1/contactBooks Create a contact book
GET /v1/contactBooks/{contactBookId} Retrieve a book
PATCH /v1/contactBooks/{contactBookId} Update a book
DELETE /v1/contactBooks/{contactBookId} Delete a book
POST /v1/contactBooks/{id}/contacts Add a contact
GET /v1/contactBooks/{id}/contacts List contacts
POST /v1/contactBooks/{id}/contacts/bulk Bulk add contacts
DELETE /v1/contactBooks/{id}/contacts/bulk Bulk delete contacts
GET /v1/contactBooks/{id}/contacts/{contactId} Retrieve a contact
PATCH /v1/contactBooks/{id}/contacts/{contactId} Update a contact
PUT /v1/contactBooks/{id}/contacts/{contactId} Upsert a contact
DELETE /v1/contactBooks/{id}/contacts/{contactId} Delete a contact

Campaigns

POST /v1/campaigns Create a broadcast campaign
GET /v1/campaigns List campaigns
GET /v1/campaigns/{campaignId} Retrieve a campaign
POST /v1/campaigns/{campaignId}/schedule Schedule a send
POST /v1/campaigns/{campaignId}/pause Pause a running campaign
POST /v1/campaigns/{campaignId}/resume Resume a paused campaign
DELETE /v1/campaigns/{campaignId} Delete a campaign

Analytics

GET /v1/analytics/email-time-series Sends / deliveries / opens over time
GET /v1/analytics/reputation-metrics Bounce & complaint reputation

Errors

Errors return the matching HTTP status and a JSON body:

Error body
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid API key"
  }
}
CodeHTTPMeaning
BAD_REQUEST400Malformed or invalid parameters.
UNAUTHORIZED401Missing or invalid API key.
FORBIDDEN403Key lacks permission, or domain not allowed.
NOT_FOUND404Resource does not exist.
METHOD_NOT_ALLOWED405Wrong HTTP method for the route.
NOT_UNIQUE409Conflicts with an existing resource.
RATE_LIMITED429Too many requests — back off and retry.
INTERNAL_SERVER_ERROR500Something went wrong on our side.