curl -sS https://win.oneshotagent.com/v1/tools/email/domains \
-H "X-Agent-ID: 0x..."
const res = await fetch(
"https://win.oneshotagent.com/v1/tools/email/domains",
{ headers: { "X-Agent-ID": wallet } }
);
const { domains } = await res.json();
const { domains } = await agent.listDomains();
// → [{ domain, pool_status, warmup_score, daily_send_limit, ... }, ...]
domains = client.list_domains()["domains"]
# → [{ "domain": ..., "pool_status": ..., "warmup_score": ..., ... }, ...]
{
"agent_id": "0x2b06a0b0bD111B83509C5850d934F5Bf2076B191",
"domains": [
{
"domain": "oneshotagents.com",
"default_from": "[email protected]",
"mailbox_mode": "mailbox",
"addresses": [
{ "address": "[email protected]", "status": "active", "warmup_state": "warmed" },
{ "address": "[email protected]", "status": "active", "warmup_state": "warming" }
],
"pool_status": "paused",
"warmup_state": "degraded",
"pause_reason": "low_reputation",
"provisioning_status": "verified",
"warmup_score": 48,
"warmup_score_updated_at": "2026-06-22T10:00:46.988Z",
"warmup_started_at": "2026-06-08T15:56:20.266Z",
"daily_send_limit": 100,
"daily_sent_count": 2,
"daily_sent_date": "2026-06-21",
"last_used_at": "2026-06-21T15:53:53.738Z"
},
{
"domain": "soulhunt.ai",
"default_from": "[email protected]",
"mailbox_mode": "relay",
"addresses": [],
"pool_status": "active",
"warmup_state": "warmed",
"pause_reason": null,
"provisioning_status": "verified",
"warmup_score": 82,
"warmup_score_updated_at": "2026-06-22T10:00:46.988Z",
"warmup_started_at": null,
"daily_send_limit": 50,
"daily_sent_count": 0,
"daily_sent_date": null,
"last_used_at": null
}
]
}
Email
List Domain Pool
List every domain the caller owns, with rotation + warmup state.
GET
/
v1
/
tools
/
email
/
domains
curl -sS https://win.oneshotagent.com/v1/tools/email/domains \
-H "X-Agent-ID: 0x..."
const res = await fetch(
"https://win.oneshotagent.com/v1/tools/email/domains",
{ headers: { "X-Agent-ID": wallet } }
);
const { domains } = await res.json();
const { domains } = await agent.listDomains();
// → [{ domain, pool_status, warmup_score, daily_send_limit, ... }, ...]
domains = client.list_domains()["domains"]
# → [{ "domain": ..., "pool_status": ..., "warmup_score": ..., ... }, ...]
{
"agent_id": "0x2b06a0b0bD111B83509C5850d934F5Bf2076B191",
"domains": [
{
"domain": "oneshotagents.com",
"default_from": "[email protected]",
"mailbox_mode": "mailbox",
"addresses": [
{ "address": "[email protected]", "status": "active", "warmup_state": "warmed" },
{ "address": "[email protected]", "status": "active", "warmup_state": "warming" }
],
"pool_status": "paused",
"warmup_state": "degraded",
"pause_reason": "low_reputation",
"provisioning_status": "verified",
"warmup_score": 48,
"warmup_score_updated_at": "2026-06-22T10:00:46.988Z",
"warmup_started_at": "2026-06-08T15:56:20.266Z",
"daily_send_limit": 100,
"daily_sent_count": 2,
"daily_sent_date": "2026-06-21",
"last_used_at": "2026-06-21T15:53:53.738Z"
},
{
"domain": "soulhunt.ai",
"default_from": "[email protected]",
"mailbox_mode": "relay",
"addresses": [],
"pool_status": "active",
"warmup_state": "warmed",
"pause_reason": null,
"provisioning_status": "verified",
"warmup_score": 82,
"warmup_score_updated_at": "2026-06-22T10:00:46.988Z",
"warmup_started_at": null,
"daily_send_limit": 50,
"daily_sent_count": 0,
"daily_sent_date": null,
"last_used_at": null
}
]
}
Authentication
RequiresX-Agent-ID header with your wallet address. Free read endpoint —
no x402 payment required.
Response
string
The caller’s wallet (echoed).
array
Every non-
removed domain the caller owns. Ordered by created_at
ascending (oldest first), matching how agents typically think about
their pool (“first I bought…”).Each domain
string
The bare domain —
oneshotagents.com, cina-lolucci.soulhunt.ai, etc.string
The canonical sending address for this domain (e.g.
[email protected]) — the
default mailbox used when you don’t pick a specific one. It’s a real mailbox like
any other: the first send from it incurs the one-time mailbox_provisioning_fee
(it’s in addresses[] as active afterward, then free). To use it, pass it as
from_address on /email/quote and /email/send.
(Omitting from_address does not default to it on an explicit send — it triggers
domain rotation at quote time, and
on /email/send returns 400 missing_from_address unless replaying a rotation
quote or a threaded reply.)string
mailbox or relay — which side of the provisioning fee this domain sits on.mailbox— a real mailbox is provisioned and warmed per address. Every address that isn’t already listedactiveinaddresses[]bills the one-timemailbox_provisioning_feeon its first send, including the canonicaldefault_from. Once that address isactive, it’s free forever.relay— header-only send. Any from-address works, nothing is provisioned, and the fee is always0.
This is a property of the domain, fixed when the domain was set up — not of
the call. Omitting
mailbox_mode on /email/quote
does not make a send relay: the mailbox_mode request parameter only chooses
a mode while a domain is still unprovisioned (brand new, or owned with
provisioning_status: "unprovisioned"), and a provisioned domain always uses
its own. So a domain created in mailbox mode charges the fee for each new
address even if you never pass mailbox_mode again — and passing
from_mailbox has no bearing on it either way. Read this field to know which of
your domains charge, and mailbox_provisioning_fee on the quote for the exact
amount before you pay.object[]
The mailboxes already provisioned on this domain — on a
mailbox_mode: "mailbox"
domain, the entries with status: "active" are exactly the addresses that are now
free to send from. Sending from any address without an active entry here
bills the one-time mailbox_provisioning_fee — being listed is not enough, since
a provisioning or failed entry still charges. On a relay domain nothing is
provisioned and the fee is always 0. Don’t infer
pricing from an empty addresses[] alone — pair it with mailbox_mode, and read
mailbox_provisioning_fee on the /email/quote
response for the number you’ll actually be charged (0 = nothing extra billed).
Each entry:Show address entry
Show address entry
string
The full email address (lowercased), e.g.
[email protected].string
Mailbox provisioning state —
active, provisioning, or failed. Only
active counts as already-provisioned (free to send from).string
Per-address reputation health —
warming, warmed, or degraded (same
meaning as the domain-level warmup_state). Each provisioned address is
warmed individually.string
Rotation eligibility only. One of:
active— eligible for rotation.paused— out of rotation. Seepause_reasonfor why and whether it self-heals.removed— never returned by this endpoint.
warming value is deprecated — warmup lifecycle now lives in
warmup_state.)string
Reputation health, orthogonal to rotation. A domain can be
paused
and warming at the same time. One of:warming— building reputation, not yet graduated.warmed— reputation>= WARMUP_ACTIVE_THRESHOLD(default 75); healthy.degraded— reputation fell< MIN_ROTATION_SCORE(default 60) after the warmup grace period.
string | null
Why the domain is out of rotation (
null when active):warming— not yet graduated to rotation.low_reputation— auto-demoted by the reconciler. Self-heals: returns toactiveautomatically oncewarmup_stateiswarmedagain. No manual resume needed.manual— paused via/domains/:domain/pause. Stays paused until you resume it; the reconciler will not auto-recover it.
string
Underlying provisioning state —
unprovisioned, provisioning,
verified, or blocked. Distinct from pool_status: a verified row
can still be out of rotation if warmup_state hasn’t reached warmed.integer | null
Latest reputation warmup score (0-100). Refreshed daily by the
reconciler;
null until the first poll lands. Drives warmup_state
(warmed at >= WARMUP_ACTIVE_THRESHOLD, degraded at
< MIN_ROTATION_SCORE), which in turn drives rotation auto-recovery.string | null
When
warmup_score was last refreshed by the reconciler (ISO 8601),
or null before the first poll.string | null
When the domain was enrolled in warmup (ISO 8601).
null for
domains that predate the warmup integration and haven’t been
backfilled.integer
Per-domain per-UTC-day cap consumed by the rotation selector. Defaults
to
50; freshly-enrolled domains start at WARMUP_DAY1_LIMIT (default
20) and ramp via the lifecycle reconciler.integer
Count of recipient-units sent today (resets when
daily_sent_date
rolls over). Incremented by both rotation picks and pinned sends
(explicit from_address), so it reflects total usage — but only rotation
is gated by daily_send_limit; pinned sends count yet aren’t blocked.string | null
UTC date the current
daily_sent_count belongs to.string | null
When this domain was last picked by rotation (drives LRU ordering).
curl -sS https://win.oneshotagent.com/v1/tools/email/domains \
-H "X-Agent-ID: 0x..."
const res = await fetch(
"https://win.oneshotagent.com/v1/tools/email/domains",
{ headers: { "X-Agent-ID": wallet } }
);
const { domains } = await res.json();
const { domains } = await agent.listDomains();
// → [{ domain, pool_status, warmup_score, daily_send_limit, ... }, ...]
domains = client.list_domains()["domains"]
# → [{ "domain": ..., "pool_status": ..., "warmup_score": ..., ... }, ...]
{
"agent_id": "0x2b06a0b0bD111B83509C5850d934F5Bf2076B191",
"domains": [
{
"domain": "oneshotagents.com",
"default_from": "[email protected]",
"mailbox_mode": "mailbox",
"addresses": [
{ "address": "[email protected]", "status": "active", "warmup_state": "warmed" },
{ "address": "[email protected]", "status": "active", "warmup_state": "warming" }
],
"pool_status": "paused",
"warmup_state": "degraded",
"pause_reason": "low_reputation",
"provisioning_status": "verified",
"warmup_score": 48,
"warmup_score_updated_at": "2026-06-22T10:00:46.988Z",
"warmup_started_at": "2026-06-08T15:56:20.266Z",
"daily_send_limit": 100,
"daily_sent_count": 2,
"daily_sent_date": "2026-06-21",
"last_used_at": "2026-06-21T15:53:53.738Z"
},
{
"domain": "soulhunt.ai",
"default_from": "[email protected]",
"mailbox_mode": "relay",
"addresses": [],
"pool_status": "active",
"warmup_state": "warmed",
"pause_reason": null,
"provisioning_status": "verified",
"warmup_score": 82,
"warmup_score_updated_at": "2026-06-22T10:00:46.988Z",
"warmup_started_at": null,
"daily_send_limit": 50,
"daily_sent_count": 0,
"daily_sent_date": null,
"last_used_at": null
}
]
}
Notes
- This is a read-only inventory. To pause / resume rotation on a domain, see pause and resume.
- Soul-owned domains (set via
domains.soul_agent_id) are NOT returned here — this endpoint scopes byagent_idonly. - Use this before a high-volume send burst to confirm there’s enough
capacity left in the pool today. If
sum(daily_send_limit - daily_sent_count)acrossactiverows is below your batch size, consider buying another domain or waiting for the UTC rollover.