Skip to main content
POST
/
v1
/
tools
/
email
/
quote
curl -X POST https://win.oneshotagent.com/v1/tools/email/quote \
  -H "Content-Type: application/json" \
  -H "X-Payment-Proof: <your_x402_signature>" \
  -d '{
    "from_address": "[email protected]",
    "to_address": "[email protected]",
    "subject": "Hello",
    "body": "Test email"
  }'
{
  "domain": "yourdomain.com",
  "is_new": true,
  "available": true,
  "registration_fee": 10.0,
  "service_fee": 0.01,
  "total_cost": 10.01,
  "currency": "USD",
  "quote_id": "quote_abc123",
  "status": "unprovisioned"
}

Authentication

Requires X-Agent-ID header with your wallet address.

Request Body

from_address
string
Sender email address (e.g., [email protected]).If omitted, the server picks one from the agent’s domain pool via domain rotation: LRU + per-day capacity + warmup-score gates over every pool_status='active' row the caller owns. The chosen address is echoed back as from_address in the response and locked into the quote — the matching /email/send replays it automatically, so the caller can either omit from_address on send or pass the same value. Passing a different address on send returns 400 from_address_mismatch.If provided, the pool is bypassed and the server only checks domain ownership. Use this when you want to pin sends to a specific mailbox (e.g. [email protected] vs [email protected]).
to_address
string | string[]
required
Recipient email address(es)
subject
string
required
Email subject line
body
string
required
Email body content (plain text)

Response

domain
string
Domain extracted from from_address
is_new
boolean
Whether this is a new domain that needs registration
available
boolean
Whether the domain is available for registration
registration_fee
number
Cost to register the domain (USD)
service_fee
number
Cost to send the email (USD)
total_cost
number
Total cost (registration + service fees)
quote_id
string
Quote ID to use in the send request
status
string
Domain status: verified, provisioning, unprovisioned, or blocked
from_address
string
Echoed only when the server picked the address (caller omitted it). Use it on /email/send or omit from_address on send — the value is locked into the quote and replayed automatically.
rotation
boolean
true when the server picked from the agent’s active pool.
rotation_fallback
boolean
true when the agent had no eligible pool entry (empty or all paused/ out-of-capacity) and the server fell back to the shared infrastructure domain (default [email protected]).
warning
string
Present only on the fallback path. pool_exhausted means the agent has domains in the pool but none were eligible (paused, over daily cap, or below MIN_ROTATION_SCORE). Worth surfacing to the user — paid-for capacity is sitting idle.
curl -X POST https://win.oneshotagent.com/v1/tools/email/quote \
  -H "Content-Type: application/json" \
  -H "X-Payment-Proof: <your_x402_signature>" \
  -d '{
    "from_address": "[email protected]",
    "to_address": "[email protected]",
    "subject": "Hello",
    "body": "Test email"
  }'
{
  "domain": "yourdomain.com",
  "is_new": true,
  "available": true,
  "registration_fee": 10.0,
  "service_fee": 0.01,
  "total_cost": 10.01,
  "currency": "USD",
  "quote_id": "quote_abc123",
  "status": "unprovisioned"
}

Bulk Usage

You can request a quote for sending independent emails to multiple recipients in a single request. Pass an array of strings to to_address.
The service_fee will scale based on the number of recipients. The registration_fee (if applicable) remains a one-time cost for the domain.
curl -X POST https://win.oneshotagent.com/v1/tools/email/quote \
  -H "Content-Type: application/json" \
  -H "X-Payment-Proof: <your_x402_signature>" \
  -d '{
    "from_address": "[email protected]",
    "to_address": ["[email protected]", "[email protected]", "[email protected]"],
    "subject": "Hello Team",
    "body": "Weekly update..."
  }'

Domain Rotation

If the caller owns multiple domains (root or subdomains), /email/quote without from_address rotates across them instead of hardcoding one. The selector runs in a single FOR UPDATE SKIP LOCKED query so concurrent quote calls never double-book the same row past its daily cap. Eligibility gates (applied in SQL, AND-combined):
  • agent_id = caller
  • pool_status = 'active' (warming domains stay out of rotation until their reputation warmup score crosses WARMUP_ACTIVE_THRESHOLD)
  • daily_sent_count + recipientCount <= daily_send_limit (per-domain per-UTC-day cap; resets lazily on the first send after midnight)
  • warmup_score IS NULL OR warmup_score >= MIN_ROTATION_SCORE (default 60)
Ordering: last_used_at ASC NULLS FIRST (least-recently-used first). Side effects on success: last_used_at = NOW(), daily_sent_count += recipientCount. Committed at quote time so concurrent quotes can’t race past capacity. If you bail without calling /email/send, the reservation auto-releases (best-effort).

Picking a specific domain

Just pass from_address and the pool is skipped:
curl -X POST https://win.oneshotagent.com/v1/tools/email/quote \
  -H "X-Agent-ID: <wallet>" -H "Content-Type: application/json" \
  -d '{
    "from_address": "[email protected]",
    "to_address": ["[email protected]"],
    "subject": "hi", "body": "..."
  }'

Letting the server rotate

curl -X POST https://win.oneshotagent.com/v1/tools/email/quote \
  -H "X-Agent-ID: <wallet>" -H "Content-Type: application/json" \
  -d '{
    "to_address": ["[email protected]"],
    "subject": "hi", "body": "..."
  }'
# →  { "from_address": "[email protected]", "rotation": true, "quote_id": "...", ... }
The mailbox local-part the server picks is ROTATION_DEFAULT_MAILBOX (env; default agent). For per-mailbox control on each domain, pass from_address explicitly. See GET /email/domains to inspect what’s in your pool, and the pause / resume endpoints to take a domain in or out of rotation without removing it.

Notes

  • Domain provisioning happens automatically during the send request
  • Quote is valid for 1 hour
  • For existing verified domains, registration_fee will be 0