API Reference

Quickstart

Authenticate, load your audience, and preview your first send in about five minutes. Every request below is real: run them in order against your own team and you end with a drafted newsletter and a previewed — not sent — delivery.

Base URLhttps://api.mailneo.co/api/v2
Building with an AI agent instead of by hand? Mailneo ships an MCP server, agent skills and an n8n node that wrap this API — start from the Resources pages: MCP & Claude connector or agent skills.

1. Get your API key

Create a key under Settings → API keys. The API needs the Business plan; the secret is shown once, at creation, and stored hashed — if you lose it, rotate the key. Live keys start mk_live_, test keys mk_test_ — the two environments are strictly separate, and test keys can never send mail.

A key holds only the scopes you grant it. Start read-only (lists:read, subscribers:read, newsletters:read) and widen the grant when a request answers insufficient_scope — the error names the exact scope it needs. To run every step on this page you will eventually want lists:write, subscribers:write, newsletters:write and newsletters:send. The full model is on the authentication page.

2. Make your first call

GET /me needs no scope at all, which makes it the right first call: it tells you which team the key belongs to, which scopes it actually has, and which API version it is pinned to.

curl "https://api.mailneo.co/api/v2/me" \
  -H "x-api-key: $MAILNEO_API_KEY"
{
  "data": {
    "object": "api_key",
    "id": "...",
    "key_id": "mk_live_a1b2c3d4e5",
    "environment": "LIVE",
    "team": { "id": "..." },
    "role": "ADMIN",
    "role_at_issue": "ADMIN",
    "api_version": "2026-08-15",
    "scopes": ["lists:read", "lists:write", "subscribers:read", "subscribers:write"],
    "granted_scopes": ["lists:read", "lists:write", "subscribers:read", "subscribers:write"]
  },
  "meta": { "request_id": "req_..." }
}

Every success has this envelope: the payload under data, everything about the response under meta. meta.request_id is what support asks for.

3. Create a list and add subscribers

Newsletters go to the subscribers of a list, so build that first: create the list, create a subscriber, attach one to the other. A newly created subscriber is on nolist until you attach them — and the attach route lets the list's own opt-in setting decide how the subscription starts.

# A list to hold the audience (lists:write)
curl -X POST "https://api.mailneo.co/api/v2/lists" \
  -H "x-api-key: $MAILNEO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Product updates", "optin": "SINGLE" }'

# A subscriber (subscribers:write). The Idempotency-Key makes the
# write safe to retry on a timeout.
curl -X POST "https://api.mailneo.co/api/v2/subscribers" \
  -H "x-api-key: $MAILNEO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: quickstart-ada-2026-08-04" \
  -d '{ "email": "ada@example.com", "first_name": "Ada" }'

# Attach the subscriber to the list (lists:write)
curl -X POST "https://api.mailneo.co/api/v2/lists/$LIST_ID/subscribers" \
  -H "x-api-key: $MAILNEO_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{ \"subscriber_ids\": [\"$SUBSCRIBER_ID\"] }"

The Idempotency-Key header makes the create safe to retry: the same key replays the original response instead of writing twice. Details on the idempotency page. A duplicate email answers 409 resource_already_exists — the remedy is to PATCH the existing subscriber, not re-POST it.

4. Draft a newsletter

POST /newsletters creates a one-off broadcast, always in the DRAFT state.

curl -X POST "https://api.mailneo.co/api/v2/newsletters" \
  -H "x-api-key: $MAILNEO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: quickstart-first-issue" \
  -d '{
    "name": "First issue",
    "subject": "Hello from the Mailneo API",
    "from_email": "news@yourdomain.com",
    "body": "<h1>It works</h1><p>Drafted over the API.</p>"
  }'
Writes are drafts-only, deliberately. status, send_at and send_days are refused by name with a 400, never silently ignored — scheduling or starting a send belongs to newsletters:send and its own preview/confirm flow, which is the next step. The sending page explains why.

One thing still happens in the app: open the draft and attach your list as its audience. List targeting through the API is planned as its own sub-resource; until it ships, a draft created here has no recipients.

5. Preview the send

POST /newsletters/{newsletterId}/send-preview resolves exactly what a send would do — recipients remaining after opt-in and suppression filtering, credits required, daily-cap headroom, the complaint breaker — runs every send gate read-only, and returns the impact plus a single-use confirmation token bound to that exact plan. Nothing is scheduled or sent by this call.

# No body. The Idempotency-Key header is REQUIRED on this endpoint.
curl -X POST "https://api.mailneo.co/api/v2/newsletters/$NEWSLETTER_ID/send-preview" \
  -H "x-api-key: $MAILNEO_API_KEY" \
  -H "Idempotency-Key: quickstart-preview-1"
{
  "data": {
    "object": "newsletter_send_preview",
    "newsletter_id": "...",
    "recipients": { "total": 1, "not_opted_in": 0, "suppressed": 0, "eligible": 1 },
    "credits_required": 1,
    "send_cap": { "limit": 2000, "used_today": 0, "remaining": 2000 },
    "from_address": "news@yourdomain.com",
    "sending_account_address": "news@yourdomain.com",
    "complaint_rate": { "rate": 0, "threshold": 0.002, "window_days": 30 },
    "confirmation": { "token": "...", "expires_at": "2026-08-04T12:15:00Z" }
  },
  "meta": { "request_id": "req_..." }
}
Confirming is a separate, deliberate call: POST /newsletters/{newsletterId}/send with the confirmation_token — made once a human has read the numbers above. The token expires after 15 minutes and is invalidated by any change to the plan, so the send that happens is provably the send that was shown. The full flow, including every gate that can refuse it, is on the sending page.

6. Confirm it worked

Read your work back. The draft is in the newsletter list with "status": "DRAFT"; once you confirm a send and it completes, the same endpoint carries its counts, and GET /analytics/overview (scope analytics:read) reports delivery and engagement event totals.

curl "https://api.mailneo.co/api/v2/newsletters?limit=5&sort=updated_at&order=desc" \
  -H "x-api-key: $MAILNEO_API_KEY"

Next steps

The endpoint reference

Every endpoint, parameter and response schema, generated from the API's OpenAPI specification — it describes exactly what is deployed, not a copy that can fall behind.