Home / Send API
API Guide

Send API & Batch Send API

MailLogic provides Send API and Batch Send API. Send a message with optional attachments, or submit separate personalized emails in one batch.

https://api.maillogic.ioAuthorization: Bearer YOUR_API_KEY

These endpoints use domain API keys, not PATs. For management operations and automation tokens, see API Docs.

Before you send

Select your domain in the dashboard, open API, and generate an API key. Copy the full key when it is shown; it cannot be viewed again. Regenerating it replaces the previous key. Keep it on your server, outside browser code.

API access requires a plan that includes it. The From address must be an active MailLogic email account on the key’s domain, with SMTP enabled and a password set. Domain ownership and sending DNS must be verified.

Use Authorization: Bearer YOUR_API_KEY for every endpoint below. X-API-Key is also supported. Replace the key and all .example addresses before running examples. Python examples require pip install httpx.

Send API

POST /v1/send accepts form data, not a JSON body. Send text, HTML, or both. Repeat to_email to send the same message to multiple recipients.

Optional: add an Idempotency-Key header (1–128 characters). Use a new key for each new email, and reuse the same key, API key, and payload when retrying. A completed request returns its original result without sending or charging again. Without this header, each request is a separate send.

Ordinary customer Send API requests share an account-wide limit of one new SMTP submission per second across all API keys and domains, with no accumulated burst allowance. Requests sent too soon receive HTTP 429 (send_api.rate_limit_exceeded) and an integer Retry-After in seconds. Wait at least that long, then retry the same logical request with the same Idempotency-Key, API key, and payload. Rejections do not reserve a future slot or extend the wait; completed idempotent replays do not count as new submissions. This limits submissions, not delivered recipients: one request may contain up to 100 recipients.

FieldUsage
from_emailRequired. Active sender on the API key’s domain.
to_emailRequired. One address per field; repeat for multiple recipients.
subjectRequired form field. Supply a subject or message content.
text_content
html_content
Optional text and HTML bodies.
display_nameOptional override. Omitted or blank uses the Accounts Display Name; if unset, the bare address is used.
attachmentsOptional file uploads; repeat for multiple files.
request.sh
# Optional: add --header "Idempotency-Key: welcome-email-001" to this command.
curl --request POST https://api.maillogic.io/v1/send \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --form-string "[email protected]" \
  --form-string "display_name=MailLogic Support" \
  --form-string "[email protected]" \
  --form-string "subject=Hello from MailLogic" \
  --form-string "text_content=Thanks for signing up."

For an attachment, append --form "attachments=@./welcome.pdf" to curl. In Python, open the file with with open("welcome.pdf", "rb") as file: and pass files={"attachments": ("welcome.pdf", file, "application/pdf")} to httpx.post inside that block.

Example response: 200 OK
200 OK
{
  "status": "success",
  "message": "Email sent from [email protected] to [email protected]",
  "message_id": "[email protected]",
  "from_email": "[email protected]",
  "to_email": [
    "[email protected]"
  ],
  "accepted_recipients": [
    "[email protected]"
  ],
  "rejected_recipients": [],
  "suppressed_recipients": [],
  "recipient_count": 1,
  "accepted_recipient_count": 1,
  "rejected_recipient_count": 0,
  "suppressed_recipient_count": 0
}

Batch Send API

Send separate personalized messages asynchronously using JSON. Each recipient has an email and a variables object. Reference values with {{variable_name}} in a required subject_template and at least one of text_template or html_template.

Save this payload as batch.json. The same file is used for preview and creation.

batch.json
{
  "from_email": "[email protected]",
  "subject_template": "Your {{month}} invoice",
  "text_template": "Hi {{name}}, your balance is {{amount}}.",
  "html_template": "<p>Hi {{name}}, your balance is {{amount}}.</p>",
  "recipients": [
    {
      "email": "[email protected]",
      "variables": {
        "name": "Alice",
        "month": "September",
        "amount": "$42"
      }
    },
    {
      "email": "[email protected]",
      "variables": {
        "name": "Bob",
        "month": "September",
        "amount": "$18"
      }
    }
  ]
}

1. Validate and preview

POST /v1/batch-send/preview validates the payload without sending. The response includes up to five rendered previews, warnings, sendable/suppressed recipient counts, and quota information.

preview.sh
curl --request POST https://api.maillogic.io/v1/batch-send/preview \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --data @batch.json

2. Create the batch

POST /v1/batch-send requires an Idempotency-Key header of 1–128 characters. Use a new key for each new batch. Retry the same payload with the same key to avoid creating a duplicate; a conflicting payload returns 409.

request.sh
curl --request POST https://api.maillogic.io/v1/batch-send \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: invoices-2026-09-001" \
  --data @batch.json

A successful request returns 202 Accepted with batch, duplicate, and quota. Read batch.id to check progress. duplicate: true means the existing batch was returned.

3. Check progress

status.sh
curl https://api.maillogic.io/v1/batch-send/BATCH_ID \
  --header "Authorization: Bearer YOUR_API_KEY"

Replace BATCH_ID with batch.id. GET /v1/batch-send/{batch_id} returns the batch object directly. Poll periodically for status and submission counts (sent_count, failed_count, unknown_count), plus delivery outcomes: accepted_count, deferred_count, bounced_count, delivery_failed_count, pending_count, and suppressed_count.

Batch size depends on your plan; check the dashboard API section for your current limit. Batch Send API uses the sender’s saved Display Name at creation time and does not accept attachments or a request-level display_name.

Credits for all sendable recipients are reserved before the batch starts. If credits are insufficient, the batch waits without partially sending. Purchase credits or enable optional automatic top-up in Billing. Suppressed recipients use no credits.

Responses and troubleshooting

An HTTP success response confirms submission, not final delivery. For Send API, inspect status and the accepted, rejected, and suppressed recipient arrays and counts. partial_success means some recipients were rejected or suppressed; suppressed means none were submitted. Batch submission completion also does not mean all recipients received the email.

For errors, read the response’s detail (a message, structured error, or validation list). Check the key and plan for authentication/access errors, sender and DNS setup for authorization errors, and fields or template variables for 422. For Send API, 402 means more credits are needed; retry after payment succeeds. For batch 409 conflicts, check the idempotency key and payload; for 429, slow down requests.

For Send API retries, keep the same Idempotency-Key, API key, and payload. Reusing a key with different content returns 409 idempotency_key_conflict. For request_in_progress or submission_recording_pending, wait as directed by Retry-After and retry with the same key. If you receive submission_outcome_unknown, investigate the existing request; do not resend with a new key. A replayed successful result includes Idempotency-Replayed: true.

See email delivery troubleshooting for delivery outcomes and suppression.

Get your API key

Open API in your dashboard to get started.