Mailboxes & Domains
Mailboxes
| Method | Path | Description |
|---|---|---|
GET | /mailboxes | List mailboxes. ?email= finds one by address (case-insensitive) |
GET | /mailboxes/:id | One mailbox, same fields as a list row |
GET | /mailboxes/issues | Mailboxes with a problem you need to fix (see below) |
PUT | /mailboxes/by-email/:email | Add or update a Gmail / Google Workspace mailbox by address, with its app password |
POST | /mailboxes/bulk-import | Import mailboxes via their own SMTP/IMAP credentials |
PATCH | /mailboxes/:id | Update settings, including SMTP/IMAP credentials (not for OAuth-connected mailboxes) |
DELETE | /mailboxes/:id | Delete — refuses (409) if the mailbox has real send/reply history |
PATCH | /mailboxes/bulk-daily-cap | Set the same daily send cap on many mailboxes at once |
POST | /mailboxes/:id/start-warmup | Begin (or restart) the warmup ramp |
POST | /mailboxes/:id/stop-warmup | Pause warmup |
POST | /mailboxes/:id/resume-warmup | Resume a paused ramp on the day it had reached |
PATCH | /mailboxes/:id/warmup | Change one mailbox’s warmup settings without restarting its ramp |
POST | /mailboxes/:id/test-send | Send a real test email to confirm credentials work |
POST | /mailboxes/:mailboxId/tags | Attach a tag |
DELETE | /mailboxes/:mailboxId/tags/:tagId | Remove a tag |
PATCH /mailboxes/:id fields: dailySendCap (max 20), smtpHost, smtpPort, imapHost,
imapPort, smtpUsername, smtpPassword, sendingEnabled, assumedWarm, signatureHtml,
senderName, warmupGroup.
warmupGroup splits one workspace into separate warmup networks: a mailbox only ever warms with
mailboxes of its own workspace and group, plus the Sendbox seed pool. Leave it unset (or send
null) for the workspace’s default network.
PUT /mailboxes/by-email/:email body: appPassword (required; spaces are ignored), senderName,
tagIds (mailbox tags, added, never removed), warmupGroup. The app password is checked against
smtp.gmail.com first; if Google refuses it nothing is saved (400, or 502 if Google could not be
reached). Returns the mailbox row plus created: 201 when it was created, 200 when an existing
mailbox’s login was replaced (its warmup and history are kept). Safe to repeat.
POST /mailboxes/:id/start-warmup fields (all optional, falling back to your workspace’s saved
preset for that provider type, then a sane default): startingVolume, dailyIncrease,
targetVolume, replyRateMinPct, replyRateMaxPct. Starting a mailbox that is already warming
restarts its ramp at day 0.
An address warms in one workspace only. Starting or resuming warmup for an address that is already
warming in another workspace returns 409 with the reason. Resuming many mailboxes at once skips
that one (it is listed in skipped with the reason) and resumes the rest.
POST /mailboxes/:id/resume-warmup continues a paused ramp where it stopped and returns dayIndex
and resumedMidRamp (false only for a mailbox paused before 26 Sep 2026, which restarts at day 0).
PATCH /mailboxes/:id/warmup takes the same fields as start-warmup, all optional, and keeps the
ramp’s current day.
Mailbox problems
GET /mailboxes/issues returns mailboxes (how many have a problem) and issues, one per problem:
{ mailboxId, email, kind, since, detail, fix }. detail is the error from the mail server, when
there is one. fix says what to do.
kind | Meaning |
|---|---|
LOGIN_FAILING | Its SMTP login is refused. Nothing sends from it, campaign or warmup |
READ_FAILING | Its replies have not been readable for 30 minutes or more. Replies stop reaching the inbox |
AUTO_PAUSED | It was paused because too many of its emails bounced |
A mailbox you paused yourself reports no problem.
Domains
| Method | Path | Description |
|---|---|---|
GET | /domains | List sending domains with deliverability status |
POST | /domains/:id/check | Run an on-demand SPF/DKIM/DMARC/MX + blacklist recheck |
Analytics
| Method | Path | Description |
|---|---|---|
GET | /analytics/overview | Workspace totals. Query: days? (see below) |
GET | /analytics/mailboxes | Per-mailbox health/warmup/cap/bounce-rate |
GET | /analytics/mailbox-stats | Campaign sending per mailbox for a period (see below). Query: from, to or days, domain? |
GET | /analytics/domain-stats | The same per sending domain. Query: from, to or days |
GET | /analytics/bounces | Bounced emails with the reason. Query: from, to or days, kind?, mailboxId?, domain?, page, limit (max 200) |
GET | /analytics/timeseries | Daily-bucketed workspace totals. Query: days? (max 90) |
GET /analytics/overview returns totalSent, leadsContacted, totalOpened, totalClicked,
totalReplied, totalPositive, totalBounced, totalLeads, totalMailboxes, and openRate,
clickRate, replyRate, positiveRate, bounceRate.
totalSentandtotalBouncedare emails;bounceRateis overtotalSent.totalOpened,totalClicked,totalRepliedandtotalPositiveare leads, each counted once; their rates are overleadsContacted.opensTracked/clicksTrackedarefalsewhen no campaign in the workspace tracks opens or clicks. Those numbers then mean nothing.
These are the same rules as campaign stats.
Per mailbox and per domain
The period: from and to (an ISO date or date-time; to is not included, and a bare date is
midnight UTC), or days back from now. Default: the last 30 days. At most 366 days.
GET /analytics/mailbox-stats returns { from, to, mailboxes }. Each mailbox has emailAddress,
domain, healthStatus, sendingEnabled, dailySendCap, and for the period:
sent,bouncedHard,bouncedSoft,bounced: emails.bounceRateis bounced over sent.failed: emails the receiving server refused at send time without it counting as a bounce (they are retried).leadsContacted,replied,positive(andopened,clicked): leads, each once.replyRateandpositiveRateare overleadsContacted.lastSentAt.
And over the last 7 days, whatever the period:
activity | Meaning |
|---|---|
active | At least its daily cap of campaign emails in 7 days |
low_activity | Some campaign email in 7 days, but fewer than its daily cap |
inactive | Campaign sending is on, but no campaign email in 7 days |
not_sending | Campaign sending is off for this mailbox |
sentLast7Days is the count behind it. Warmup mail is not counted anywhere here.
GET /analytics/domain-stats returns { from, to, domains }: the same numbers per sending domain,
with mailboxes, spfStatus, dkimStatus, dmarcStatus. A domain’s activity is the best of its
mailboxes’.
GET /analytics/bounces returns { from, to, bounces, total, page, limit }, newest first. Each has
kind (hard or soft; with kind=failed, emails refused at send time), at, code (the SMTP
code or enhanced status, e.g. 550 or 5.1.1), reason (the server’s message), leadEmail,
mailboxEmail, domain, campaign and stepOrder (0 is the first step). Without kind, hard and
soft bounces are listed. code and reason are null on bounces from before 2 Oct 2026.
Inbox placement tests
| Method | Path | Description |
|---|---|---|
POST | /placement-tests | Send a probe from a mailbox and measure inbox vs. spam placement |
GET | /placement-tests | List past tests |
GET | /placement-tests/:id | Get one test’s per-seed results |