By default a Lumbox inbox gets an address on the shared trylumbox.com domain. That is fine for sign-up flows and tests. When the agent writes to customers, or when a service refuses addresses on domains it does not recognise, you want addresses on a domain you own. This guide is the setup itself: which domain to use, the DNS records, verification, creating inboxes, and how to catch mail for addresses you have not created yet.
Pick a subdomain first
MX records decide where all mail for a domain goes. If example.com already receives your team's mail through Google Workspace or Microsoft 365 and you point its MX records at Lumbox, your team's mail goes to Lumbox instead. Use a subdomain such as agents.example.com. Its MX records are separate from the parent's, so human mail is untouched, and agent traffic builds its own sending history. The only reason to use a root domain is that the whole domain exists for agents.
If you are not sure who hosts the domain's DNS, ask the API:
curl "https://api.lumbox.co/v1/domains/detect-provider?domain=agents.example.com" \
-H "X-API-Key: ak_your_key"
# { "domain": "...", "provider": "cloudflare", "nameservers": [...], "auto_setup_available": true }
It recognises nine providers from the nameservers, including Cloudflare, Route 53, Vercel, Google, DigitalOcean, Namecheap and GoDaddy. auto_setup_available is only true for Cloudflare.
Add the domain
curl -X POST https://api.lumbox.co/v1/domains \
-H "X-API-Key: ak_your_key" \
-H "Content-Type: application/json" \
-d '{"domain": "agents.example.com"}'
The 201 response has the domain's id, a status of PENDING, and a dns_records object:
{
"id": "dom_...",
"domain": "agents.example.com",
"status": "PENDING",
"dns_records": {
"verification": { "type": "TXT", "name": "agents.example.com", "value": "lumbox-verify=..." },
"mx": [ { "type": "MX", "value": "...", "priority": 10 }, { "type": "MX", "value": "...", "priority": 20 } ],
"spf": { "type": "TXT", "value": "v=spf1 include:spf.lumbox.co ~all" },
"dkim": { "type": "CNAME", "name": "lumbox._domainkey.agents.example.com", "value": "..." },
"dmarc": { "type": "TXT", "name": "_dmarc.agents.example.com", "value": "v=DMARC1; p=none; ..." },
"ses_dkim_1": { "type": "CNAME", "name": "..._domainkey.agents.example.com", "value": "....dkim.amazonses.com" }
},
"instructions": "Add these DNS records at your domain registrar, then call POST /v1/domains/:id/verify"
}
The ses_dkim_1 to ses_dkim_3 entries appear when Lumbox registered the domain with Amazon SES for sending, which happens in the same call. A domain name can only be registered to one Lumbox organization. Adding one that is already registered returns 409.
Publish the records
Copy every record from the response exactly: the verification TXT, both MX records with their priorities, the SPF TXT, the DKIM CNAME, the DMARC TXT, and the three SES DKIM CNAMEs if present. Three mistakes account for most failed setups:
- A second SPF record. If the name already has a
v=spf1record, addinclude:spf.lumbox.coto it. Two SPF records on one name make SPF fail for everything. - Doubled names. Many DNS dashboards append the zone automatically, so typing
agents.example.cominto the name field of theexample.comzone createsagents.example.com.example.com. Enteragents, or the part before the zone. - Proxied records. On Cloudflare, MX targets and the DKIM CNAMEs must be DNS-only, not proxied.
If the zone is on Cloudflare, Lumbox can create the records for you:
curl -X POST https://api.lumbox.co/v1/domains/dom_.../auto-setup \
-H "X-API-Key: ak_your_key" \
-H "Content-Type: application/json" \
-d '{"cf_api_token": "your_cloudflare_token"}'
The token needs to read the zone and edit its DNS records. The response lists each record as created, already_exists or failed with the error, MX and CNAME records are created unproxied, and if every record was created, the same call runs the verification check. The token is used for that request and is not saved. Auto-setup does not merge with an existing SPF record, so if the name already had one, fix that by hand afterwards.
Verify
curl -X POST https://api.lumbox.co/v1/domains/dom_.../verify -H "X-API-Key: ak_your_key"
# { "status": "ACTIVE", "checks": { "verification": true, "mx": true, "spf": true,
# "dkim": ..., "dmarc": ..., "ses_verified": ... }, "message": "..." }
Lumbox resolves the records through Cloudflare's public DNS-over-HTTPS resolver, so what counts is what the public internet sees, not what your DNS dashboard shows. There are three statuses. PENDING means the verification TXT was not found. DNS_CONFIGURED means ownership is proven but the MX or SPF record is still missing. ACTIVE needs the TXT, an MX pointing at Lumbox and the SPF include, and only an ACTIVE domain can hold inboxes. The status only changes when you call verify, so if a record was just added, wait for its TTL and call again. DKIM and DMARC are reported but are not required for ACTIVE; check them before you send from the domain, because they decide whether receivers can authenticate your mail. The SPF, DKIM and DMARC post explains what each result means.
Create inboxes on the domain
curl -X POST https://api.lumbox.co/v1/inboxes \
-H "X-API-Key: ak_your_key" \
-H "Content-Type: application/json" \
-d '{"name": "research-agent", "domain": "agents.example.com"}'
# { "id": "inb_...", "address": "research-agent@agents.example.com", ... }
The local part comes from local_part if you pass it, otherwise from name, lowercased with anything outside a-z, 0-9 and - turned into a hyphen. Addresses such as support@, billing@ and postmaster@ are reserved on the shared domain but allowed on your own. Each inbox counts toward your plan's inbox limit whatever its domain. From here everything works the same as on the shared domain: long-polling with /wait and /otp, webhooks, sending and replying. Verifying a domain also lifts two Free-plan limits on sending: the new-account send ramp and the recipient-domain check.
Addresses you have not created
Mail to an address with no inbox is refused during the SMTP conversation with "No such mailbox". The sender gets a bounce and nothing is stored. Plus-addressing is not special: bot+github@agents.example.com is a different address from bot@agents.example.com and needs its own inbox.
So create the inbox before the address goes anywhere. An agent that is about to give an address to a service can make it first, in one request:
curl -X POST https://api.lumbox.co/v1/inboxes \
-H "X-API-Key: ak_your_key" \
-H "Content-Type: application/json" \
-d '{"local_part": "github-bot", "domain": "agents.example.com"}'
Refusing unknown addresses also works in your favour. Spammers guess common names on any domain that accepts mail, and an address that exists only because you created it collects nothing from those guesses. Each agent's mail stays in the inbox made for it, which is what you want when the agent acts on what arrives without a person reading it first.
Next
Mail sent from these inboxes goes out through Lumbox's default provider unless you configure your own, which the bring-your-own-SMTP guide covers. For the reasons to give agents addresses on your domain in the first place, see giving your bot a professional identity. Custom domains are listed on the Starter plan and above on the pricing page.