Developer Documentation

Getting Started

From account setup through mailbox provisioning and your first sequencer campaign.

This guide walks through the fastest path from signup to a working domain, mailbox, inbox, and your first Email Sequencer campaign. Follow the steps below (sub-domains are optional), then use the links at the bottom to go deeper.

1. Create an account and API key

  • Create a Mails.now account.
  • Open Settings → API Keys in your dashboard after login.
  • Generate an API key with the permissions you need (read, write, inbound, webhook, sequencer for Email Sequencer, transactional for template-based sends).
  • Store the 32-character key securely.
  • Send it via Authorization: Bearer <key> or X-Api-Key.

Full REST reference: API docs

2. Add a domain and publish DNS records

Create a root domain with the API (write permission required):

Request Example

curl --fail-with-body --silent --show-error \
  -X POST "$APP_URL/api/v1/create/domain" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "Domain": "example.com",
    "Params": {
      "total_mailbox_allowed": 100
    }
  }'

The response includes task_id. Poll until status is completed (read permission):

Request Example

curl --fail-with-body --silent --show-error \
  -H "Authorization: Bearer $API_KEY" \
  "$APP_URL/api/v1/get/domain?task_id=$TASK_ID"

When complete, the response includes DNS records (MX, TXT verification, mail-host A). Add them at your DNS host, then verify in the dashboard.

3. Add sub-domains (optional)

Skip this step if you only need mailboxes on the root domain (for example, john@example.com).

After the parent domain is provisioned, create sub-domains in batches of up to 10 labels:

Request Example

curl --fail-with-body --silent --show-error \
  -X POST "$APP_URL/api/v1/create/sub-domain" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "Domain": "example.com",
    "Params": {
      "sub_domains": ["team", "support", "billing"]
    }
  }'

Poll the task until status is completed:

Request Example

curl --fail-with-body --silent --show-error \
  -H "Authorization: Bearer $API_KEY" \
  "$APP_URL/api/v1/get/sub-domain?task_id=$TASK_ID"

When complete, publish the returned MX records for each sub-domain hostname (for example, team.example.com). Sub-domains typically require MX verification only. See DNS verification for details.

4. Create mailboxes

Set Domain to the target hostname (root domain or sub-domain FQDN). Params.email_id must belong to that hostname.

You can also connect external senders from Settings → SMTP/IMAP (custom SMTP, Gmail App Password, or Google Workspace OAuth via the Gmail API).

Single mailbox example:

Request Example

curl --fail-with-body --silent --show-error \
  -X POST "$APP_URL/api/v1/create/mailbox/single" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "Email_fullname": "John Doe",
    "single_bulk": "single",
    "Domain": "example.com",
    "Params": {
      "email_id": "john@example.com",
      "password": 0
    }
  }'

Use numeric 0 for password to auto-generate a secure password (string "0" is rejected). Poll for credentials:

Request Example

curl --fail-with-body --silent --show-error \
  -H "Authorization: Bearer $API_KEY" \
  "$APP_URL/api/v1/get/mailbox/single?task_id=$TASK_ID"

Bulk mailbox example:

Request Example

curl --fail-with-body --silent --show-error \
  -X POST "$APP_URL/api/v1/create/mailbox/bulk" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "Email_fullname": "Team Member",
    "single_bulk": "bulk",
    "Domain": "example.com",
    "Params": {
      "mailbox_no": 25,
      "password": 0
    }
  }'

Poll bulk results with GET /api/v1/get/mailbox/bulk?task_id=$TASK_ID.

5. Receive and read email

  • Inbound HTTP: POST /api/v1/mail/inbound (requires inbound permission). See the API reference.
  • Inbox retrieval: GET /api/v1/emails, GET /api/v1/emails/sync, and related endpoints (requires read).
  • Webhooks: POST /api/v1/webhooks with url and events (email.received, email.read, email.deleted; requires webhook permission). See Webhooks.

Email Sequencer

The sections below cover multi-sender outbound campaigns. All sequencer routes require:

  • An active plan with Email Sequencer enabled (sequencer_enabled).
  • An API key with the sequencer permission.

Sequencer REST base path: /api/v1/sequencer. See the dedicated Sequencer API guide for full endpoint reference.

6. Enable Email Sequencer

Confirm your plan includes Email Sequencer on the pricing page. If your plan does not include it, upgrade before calling sequencer endpoints.

Create or update an API key with the sequencer permission in Settings → API Keys. Requests without this permission return HTTP 403.

7. Manage leads

Create a single lead (upserts by email):

Request Example

curl --fail-with-body --silent --show-error \
  -X POST "$APP_URL/api/v1/sequencer/leads" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@acme.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "company": "Acme Inc"
  }'

Bulk import (≤50 rows returns immediately; larger imports return task_id to poll):

Request Example

curl --fail-with-body --silent --show-error \
  -X POST "$APP_URL/api/v1/sequencer/leads/import" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "leads": [
      {"email": "one@acme.com", "first_name": "One"},
      {"email": "two@acme.com", "first_name": "Two"}
    ]
  }'

Segmentation — organize leads with:

  • Lists: POST /api/v1/sequencer/lead-lists (group leads for bulk enrollment)
  • Tags: POST /api/v1/sequencer/lead-tags (label leads for filtering)
  • Saved filters: POST /api/v1/sequencer/saved-filters (reusable lead index filters)
  • Notes: POST /api/v1/sequencer/lead-notes (attach notes to a lead)

List leads with filters: GET /api/v1/sequencer/leads?q=acme&list_id=1&tag=hot.

8. Build a sequence

Create a sequence and sync its steps (email, follow_up, wait, condition):

Request Example

curl --fail-with-body --silent --show-error \
  -X POST "$APP_URL/api/v1/sequencer/sequences" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Outbound intro"}'

Add steps with PUT /api/v1/sequencer/sequences/$SEQUENCE_ID/steps:

Request Example

curl --fail-with-body --silent --show-error \
  -X PUT "$APP_URL/api/v1/sequencer/sequences/$SEQUENCE_ID/steps" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "steps": [
      {
        "type": "email",
        "position": 1,
        "subject": "Quick question, {{first_name}}",
        "body": "Hi {{first_name}}, reaching out from Mails.now."
      },
      {
        "type": "wait",
        "position": 2,
        "wait_days": 3
      },
      {
        "type": "follow_up",
        "position": 3,
        "subject": "Following up",
        "body": "Wanted to bump this to the top of your inbox."
      }
    ]
  }'

When creating a campaign, you can omit sequence_id — Mails.now auto-provisions a linked sequence with the campaign name.

9. Create and configure a campaign

Create a draft campaign with multi-sender mailboxes and send settings:

Request Example

curl --fail-with-body --silent --show-error \
  -X POST "$APP_URL/api/v1/sequencer/campaigns" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q1 Outreach",
    "sequence_id": '"$SEQUENCE_ID"',
    "mailbox_ids": ['"$MAILBOX_ID"'],
    "settings": {
      "daily_send_limit": 50,
      "ramp_up_percent_per_day": 10,
      "track_opens": true,
      "track_clicks": true,
      "schedule_mode": "future"
    },
    "sending_timezone": "America/New_York",
    "sending_window": {
      "days": [1, 2, 3, 4, 5],
      "start_hour": 9,
      "start_minute": 0,
      "end_hour": 17,
      "end_minute": 0
    }
  }'

Settings reference

Key Description
daily_send_limit Starting sends per day across campaign mailboxes (must be > 0 to activate)
ramp_up_percent_per_day Optional daily ramp-up amount (percent or count per ramp_up_mode)
ramp_up_mode percent (default) or count
track_opens / track_clicks Enable open and click tracking
schedule_mode now (send immediately within window) or future (scheduled window)

Sending windowdays uses ISO weekday numbers (1 = Monday … 7 = Sunday). Hours are in the campaign sending_timezone.

10. Enroll, schedule, and launch

Assign at least one verified mailbox before enrolling. Enroll specific leads or an entire list:

Request Example

curl --fail-with-body --silent --show-error \
  -X POST "$APP_URL/api/v1/sequencer/campaigns/$CAMPAIGN_ID/enroll" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"lead_ids": ['"$LEAD_ID"']}'

Activate a draft campaign (runs readiness checks: email steps, mailboxes, daily limit, enrolled leads, active schedule):

Request Example

curl --fail-with-body --silent --show-error \
  -X PATCH "$APP_URL/api/v1/sequencer/campaigns/$CAMPAIGN_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "active"}'

If activation fails, the response includes failures with human-readable reasons (HTTP 422).

Pause and resume without deleting enrollments:

Request Example

curl -X POST "$APP_URL/api/v1/sequencer/campaigns/$CAMPAIGN_ID/pause" \
  -H "Authorization: Bearer $API_KEY"

curl -X POST "$APP_URL/api/v1/sequencer/campaigns/$CAMPAIGN_ID/resume" \
  -H "Authorization: Bearer $API_KEY"

11. Track results

Campaign analytics include funnel metrics, engagement rates, and breakdowns by mailbox, step, and recipient domain:

Request Example

curl --fail-with-body --silent --show-error \
  -H "Authorization: Bearer $API_KEY" \
  "$APP_URL/api/v1/sequencer/campaigns/$CAMPAIGN_ID/analytics"

Success Response

{
  "data": {
    "campaign_id": 1,
    "funnel": {
      "total_enrolled": 100,
      "sent": 80,
      "opened": 40,
      "clicked": 12,
      "replied": 5,
      "bounced": 2
    },
    "rates": {
      "open_rate": 50.0,
      "click_rate": 15.0,
      "reply_rate": 6.25,
      "bounce_rate": 2.5
    },
    "by_mailbox": [],
    "by_step": [],
    "by_domain": []
  }
}

12. Sequencer webhooks

Register sequencer events on the same webhook endpoint used for inbox events (webhook permission):

Request Example

curl --fail-with-body --silent --show-error \
  -X POST "$APP_URL/api/v1/webhooks" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhooks/mailsnow",
    "events": [
      "sequencer.email.sent",
      "sequencer.email.opened",
      "sequencer.lead.replied",
      "sequencer.campaign.completed"
    ],
    "is_active": true
  }'

See Webhooks for delivery security and the full event list.