Pre-Black Friday: 20% off, for as long as you stayEARLYBFon Solo and AgencyEnds Nov 28Start free

How-to guide

How to Warm Up an Email Domain (in 4 Weeks, With Real Checks)

Authenticate, ramp in gated steps, and send cold mail only to verified addresses. Commands and queries you can run today.

Get your free API key →Free to start. No credit card. 1,000 records to spend whenever you like.

Email domain warmup is a gated volume ramp on a new sending domain, and most of the work is checks, not waiting. This guide gives the DNS commands, the schedule as config, and the list query. Every step has a pass or fail test.

TL;DR

  • Setup takes about an hour: three DNS records, then mailboxes. The ramp takes four weeks.
  • Move up a step only when bounces, spam complaints and delays stay flat. Hold or step back if any rise.
  • The prospect list costs up to about 900 LeadOcean records on a three-mailbox plan (an estimate: two records per prospect). Counting it is free, and Free includes 1,000 records.

Prerequisites

  • A new sending domain, separate from your main one, with DNS access.
  • Two to three mailboxes on that domain, at Google Workspace or a similar host.
  • A sending tool or plain mail client. LeadOcean supplies people and companies, not sending.
  • Google Postmaster Tools verified for the domain.
  • A LeadOcean API key in $LEADOCEAN_API_KEY. Start free: 1,000 records, no card. Free runs at 5 requests a second.
  • dig and curl on your machine.

Step 1: Authenticate the domain

Authentication comes before the first message. Google requires SPF or DKIM from all senders, and SPF, DKIM and DMARC from anyone sending 5,000 or more messages a day (Google email sender guidelines, September 2026). Publish all three from day one.

Check each record with dig. Replace acme.com and the DKIM selector (google here) with yours.

bash
dig +short TXT acme.com | grep spf1
dig +short TXT google._domainkey.acme.com
dig +short TXT _dmarc.acme.com

Pass: each command prints a record. A starter DMARC policy that only monitors:

text
_dmarc.acme.com.  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@acme.com"

Fail: an empty line means the record is missing or not yet propagated. Wait for DNS and rerun. Do not send until all three print. Also confirm the domain has an MX record. A half-finished setup looks like a spoofed domain to a provider.

Step 2: Spend weeks 1 and 2 on people who know you

The first mail from a cold domain goes to people who will reply. Colleagues, partners and customers work. Replies are the strongest early signal, and these recipients do not report spam.

Keep each mailbox to one-to-one, plain-text messages. No links to tracked domains, no images, no attachments yet. Write real questions that get real answers.

Ask for a short reply, such as a yes or a one-line answer. Two or three real threads per mailbox per day beat a dozen unanswered messages. Do not use a script that fakes replies.

Pass: replies arrive and nothing bounces. Fail: any bounce or delay in week 1. Stop, find the cause (usually a typo in an address or a DNS record), and restart the week.

Step 3: Write the ramp as config

Providers publish no official schedule, so treat this as a plan you adjust to your own results. Writing it down makes the gates explicit.

yaml
domain: acme.com
mailboxes: 3
weeks:
  - week: 1
    per_mailbox_per_day: 5-10
    audience: people who know you
  - week: 2
    per_mailbox_per_day: 15-20
    audience: known contacts plus warm leads
  - week: 3
    per_mailbox_per_day: 25-30
    prospects_per_mailbox_per_day: 10
    audience: first verified prospect batch
  - week: 4
    per_mailbox_per_day: 35-40
    prospects_per_mailbox_per_day: 20
    audience: prospects in small batches
gate_to_move_up:
  spam_rate_max: 0.10%    # Google Postmaster Tools
  bounce_rate_max: 2%     # your own limit, not a provider number
  delays: none

Google asks senders to keep the spam rate in Postmaster Tools below 0.10% and never reach 0.30% (Google email sender guidelines, September 2026). The bounce ceiling is our suggestion, not a published rule.

Step 4: Size the prospect list for free

Bounces in the first weeks do the most damage, so decide the list before week 3. A count call tells you how many verified people match and costs nothing. Send count=true and limit=1 as query parameters, with the filters in a flat JSON body.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/search?count=true&limit=1" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jobLevel": ["VP"],
    "jobFunction": ["Sales & Business Development"],
    "country": ["US"],
    "emailStatus": ["verified"]
  }'

Enum values are exact strings. Check them first with the free GET /v1/enums endpoint or the leadocean_list_enum_values MCP tool. A wrong value returns an empty result, not an error.

Use verified only while the domain is cold. Add catch_all_valid in week 4 or later, in small batches. Leave out risky, invalid, role, disposable, spam_trap, abuse and unknown.

Pass: meta.total is well above the roughly 450 prospects the ramp needs. Fail: it is too low. Widen country or jobLevel, and recount.

Step 5: Pull the week 3 batch

Pull one week of prospects at a time, not the whole list. Week 3 on three mailboxes at 10 prospects each is about 150 a week. Search rows are a thin projection with no contact points, so take each row's meta.source_ids.person_id and enrich it with reveal_email. The enrich returns the person again, so it counts one more record.

Search for 100 people. This counts as 100 records.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jobLevel": ["VP"],
    "jobFunction": ["Sales & Business Development"],
    "country": ["US"],
    "emailStatus": ["verified"],
    "limit": 100
  }'

Then reveal the address for each meta.source_ids.person_id in the response:

bash
curl -s -X POST "https://api.leadocean.io/v1/people/enrich" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"person_id": "PERSON_ID_FROM_SEARCH", "reveal_email": true}'

Page with meta.nextCursor in the cursor field for the next page. On Solo, Agency and Platform you can instead run POST /v1/exports with the same filters under filters and a limit of up to 50,000 rows. Bulk CSV export is not on Free. The Exports page in the app does the same with a filter builder and a price preview.

Read email_status on every row again before you load the batch. LeadOcean gives no refund or credit-back for bounced emails.

Step 6: Gate every week

A gate is a rule you write before the data arrives. That removes the temptation to rationalize a bad week. Write the thresholds in the config, read the numbers, and follow them. Log each week's result in a shared sheet so a later change has a baseline to compare against.

Open Postmaster Tools each Monday and compare the week to the config. Move up only if every gate held.

SignalWhere to read itMove upHold or step back
Spam ratePostmaster ToolsUnder 0.10%0.10% or higher
BouncesYour sender's reportUnder 2%2% or higher
Delays and deferralsYour sender's logNoneAny new ones
RepliesYour inboxArrivingNone for a week

If a gate fails, cut volume to the previous week's level for five to seven days. Do not skip weeks to catch up. Keep a steady floor of daily sends after week 4, because a domain that goes quiet loses its rhythm.

What you get

A count call returns no rows, only meta. This is the response shape from the API reference, with placeholder values, not a live result.

json
{
  "success": true,
  "data": [],
  "meta": {
    "count": 0,
    "limit": 1,
    "total": 12345,
    "countOnly": true,
    "distinctCompanies": 6789
  }
}

meta.total is capped at 100,000 (OpenAPI spec, September 2026). distinctCompanies shows how many employers the matched people span, which helps you spread sends across companies. After enrich with reveal_email, the address sits in contact_data.contact_emails and the status in contact_data.email_status.

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-key headerCheck $LEADOCEAN_API_KEY is exported and the header name is x-api-key
429Above the plan's rate limit (5 a second on Free, 200 on Agency)Honor the Retry-After header and slow the loop
402Records are spent (Free is 1,000, one-off)Count first, narrow the batch, or move to a paid plan on pricing
Empty resultsEnum value not an exact string, such as vp instead of VPList valid values with GET /v1/enums and copy them exactly
Search stops pagingOne search pages to 10,000 rows, then meta.depthCapped is trueNarrow the filters instead of walking the index
Export refusedOver 50,000 rows a request or 500,000 a daySplit the export into smaller requests across days

FAQ

How long does email domain warmup take?

Plan on two to six weeks. Providers publish no official number. A clean four-week ramp reaches about 40 messages per mailbox per day. Early bounces add time.

Do I need a warmup tool?

No. Warmup tools exchange mail between a network of mailboxes. You can warm a domain with real one-to-one mail and a slow ramp. The tool is optional and does not fix a bad list or missing DNS records. See the warmup tools comparison.

Can I use a wildcard or catch-all setup?

Be careful. A wildcard domain accepts mail for any address, so a "valid" address may not exist. Read the wildcard email domain entry and keep catch-all addresses out of early batches.

What is the difference between warmup and list hygiene?

Warmup builds trust in a domain. List hygiene decides which addresses you send to. You need both. The domain warmup basics page covers the split.

Does LeadOcean send or warm email?

No. LeadOcean has no sequencer and no sending. It supplies the verified list through the API, the MCP server or the app's Exports page.

Warm up on verified addresses. Start free.

Free to start. No credit card. 1,000 records to spend whenever you like.

Get your free API key →