Winnr provides a full REST API that lets you programmatically provision domains, create mailboxes, and send email from inside your own product. If you're building an AI SDR tool, a cold email sequencer, a CRM with outreach features, or an agency management platform, you can embed production-grade email infrastructure in your app with a few API calls instead of building and maintaining SMTP servers yourself. This guide walks through the complete integration: authentication, domain setup, bulk mailbox creation, sending, and monitoring, with working code examples in cURL and Python.
Every SaaS product that touches outbound email eventually hits the same wall: where do the mailboxes come from?
If you're building an AI SDR tool, your AI agent needs real email accounts to send from. If you're building a sequencer, your users need dozens of warmed inboxes to run campaigns. If you're running an agency, you need to spin up mailboxes for every new client quickly and reliably, without clicking through a hosting control panel.
The traditional approach is painful. You either ask users to BYO their own Google Workspace or Microsoft 365 accounts (creating onboarding friction, support headaches, and suspension risk), or you build and maintain your own SMTP infrastructure (which is an entire engineering team's worth of work). Neither option scales.
There's a third path: use an API to provision fully managed email infrastructure on demand. That's what Winnr's API is built for. You make API calls, and production-ready mailboxes with DKIM, SPF, and DMARC authentication are provisioned in the background. Your users just see that email works inside your product.
This guide walks through the complete integration from first API call to sending production email, with code examples you can copy and adapt.
Why Embed Email Infrastructure?
Before diving into the technical walkthrough, here is why building email infrastructure into your product matters, and why asking users to bring their own accounts is a weak foundation.
Google Workspace and Microsoft 365 are not built for cold outreach. Both are designed for one person's day-to-day mailbox, and accounts used for high-volume cold email get throttled or suspended. If your product's value depends on sending outbound email at scale, building on top of your users' Workspace or 365 seats puts a ceiling on what they can do, and puts your support team on the hook every time an account gets suspended. (See our SMTP vs Google/Microsoft comparison and the Google Workspace alternative for cold email for the full breakdown.)
Onboarding friction kills conversion. Asking a new user to go set up Google Workspace, buy domains, configure DNS records, connect IMAP credentials, and then come back to your app is a multi-step, multi-day process. Many users drop off before they send a single email. When you provision infrastructure via API, the user signs up and mailboxes are ready without leaving your product.
You capture more revenue. If your users are paying Google $7 to $8.40 per user per month for Workspace accounts you don't control, that's revenue you're not capturing. When you embed infrastructure, you can bundle mailbox costs into your platform pricing, either as an included feature or as a transparent line item. Either way, your unit economics improve because you're providing more of the value stack.
You control the quality. With BYO accounts, you have zero control over DNS configuration, sending reputation, IP quality, or warmup status. When you provision infrastructure via API, every mailbox comes with SPF, DKIM, and DMARC configured automatically, and you decide when to enable warming. Deliverability is something you control instead of something you inherit.
Use Cases: Who Needs This
These are the most common integration patterns:
AI SDR Platforms
An AI sales development rep needs to send personalized outbound emails, monitor replies, respond, and book meetings, largely on its own. That means it needs real mailboxes that it controls end to end.
The typical integration pattern: when a user configures their AI agent, your platform calls the Winnr API to provision 5-20 mailboxes across 2-4 domains. The agent sends through these mailboxes on rotation, reads replies via the inbox API, and handles conversations. When a domain's reputation dips, the platform can provision replacement infrastructure through the same API.
AI SDR platforms benefit most from the full loop: create mailboxes (POST /v1/email-users/bulk), send emails (POST /v1/email-users/{id}/inbox/send), read replies (GET /v1/email-users/{id}/inbox), and respond in-thread using the in_reply_to and references fields. This gives your AI agent a complete, real email identity, not a forwarding alias or shared sender.
Cold Email Sequencer Platforms
Sequencer platforms like Instantly, Smartlead, and Lemlist all face the same infrastructure gap: their software orchestrates email sequences, but the actual sending infrastructure comes from the user. This creates a fragile dependency on Google Workspace and Microsoft 365 accounts that regularly get suspended, throttled, or banned.
By embedding Winnr's infrastructure, a sequencer platform can offer turnkey email accounts as part of the subscription. Users activate a campaign and the platform provisions mailboxes, connects domains and enables warming without the user ever touching a DNS record or a Google admin panel. It also removes a common support ticket: "my Google account got suspended."
CRMs with Built-In Outreach
Modern CRMs are increasingly adding outbound email features. HubSpot, Salesforce, and dozens of vertical CRMs now offer email sequences alongside their core contact management. But most of them rely on the user connecting their existing email account via OAuth, which means they inherit all of that account's limitations.
A CRM that provisions dedicated outreach infrastructure via API offers a fundamentally better experience: higher sending limits, better deliverability (because the accounts are purpose-built for outreach, not shared with the user's personal inbox), and zero risk of the user's primary email getting suspended because of outreach activity.
Agency Management Platforms
Lead generation agencies manage outreach for dozens or hundreds of clients simultaneously. Each client needs their own domains, their own mailboxes, their own sending reputation. Manually provisioning this infrastructure through a dashboard is feasible for 5 clients but breaks down completely at 50.
The API integration pattern here is straightforward: when the agency onboards a new client, the platform calls the Winnr API to register a separate set of domains for that client, provision mailboxes on them, and enable warming. Tag each client's domains with domain tags so you can filter, export and report per client, and keep every client on their own domains so one client's sending never affects another's reputation.
Email Verification and Testing Tools
Products that test email deliverability, validate email addresses, or monitor inbox placement need real mailboxes to send from and receive into. The Winnr API lets these tools provision test infrastructure programmatically and tear it down when testing is complete, without maintaining permanent infrastructure for ephemeral use cases.
Internal Tools and Automation
Not every integration is a SaaS product. Engineering teams also use the API for internal tools: automated new-hire email provisioning, marketing campaign infrastructure, customer communication systems, and notification delivery. If your team needs to create and manage email accounts programmatically, the same API works whether you're building a product or an internal tool.
How the API Works: Architecture Overview
Before writing code, it helps to understand what happens behind the scenes when you make API calls. Winnr's infrastructure is fully managed (you don't run any email servers), but understanding the architecture helps you build a more robust integration.
api.winnr.app/v1/ with Bearer token auth
Key architectural details:
- Async provisioning: Domain setup and mailbox creation are asynchronous operations. The API returns a
job_idimmediately, and provisioning happens in the background. You poll the jobs endpoint for status. - DNS management: Winnr manages DNS records (MX, SPF, DKIM, DMARC) automatically. You either point nameservers to Winnr's DNS, or provide a Cloudflare API token and Winnr writes the records directly into your Cloudflare zone. A manual mode (
manual_dns: true) returns the records for you to create yourself. - Managed sending infrastructure: Mailboxes send from Winnr's own shared, managed infrastructure. Each mailbox has its own sending identity. Dedicated IPs are optional on Enterprise at $20 per IP per month.
- Optional built-in warming: Warming is not automatic. Enable it per mailbox with
POST /v1/warming/enable($0.60 per mailbox per month) and give new mailboxes at least 2 weeks (4 on a brand-new domain) before cold sending.
The full API reference documents every endpoint, request/response schema, and error code. What follows is the practical, step-by-step integration path.
Step 1: Authentication & API Tokens
Every API call requires a Bearer token. You create tokens from the Winnr dashboard or via the API itself.
Create a token via the API
curl -X POST https://api.winnr.app/v1/auth/tokens \
-H "Authorization: Bearer YOUR_EXISTING_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My App - Production",
"permissions": ["read", "write"]
}'
Response:
{
"data": {
"id": "tok_abc123",
"name": "My App - Production",
"token": "wnr_acct123_sk_live_...",
"permissions": ["read", "write"],
"created_at": "2026-03-22T10:00:00Z"
},
"meta": { ... }
}
The full token value (wnr_...) is only returned at creation time. Store it securely in your environment variables or secrets manager. You cannot retrieve the full token later, only the token ID and metadata.
All subsequent API calls use this token:
curl https://api.winnr.app/v1/account \
-H "Authorization: Bearer wnr_acct123_sk_live_..."
Python example
import requests
WINNR_API = "https://api.winnr.app/v1"
TOKEN = "wnr_acct123_sk_live_..."
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
}
# Verify your account
resp = requests.get(f"{WINNR_API}/account", headers=headers)
print(resp.json())
# {"data": {"id": "acct_123", "name": "My Agency", "plan": "startup", ...}, "meta": {...}}
Step 2: Connect a Domain
Before creating mailboxes, you need at least one domain connected. Winnr supports two connection flows:
- Nameserver delegation: Winnr creates a DNS zone and gives you nameservers to set at your registrar. Winnr then manages all DNS records (MX, SPF, DKIM, DMARC) automatically.
- Cloudflare integration: you provide a Cloudflare API token and Winnr writes DNS records directly into your existing Cloudflare zone. No nameserver change required.
Option A: Nameserver delegation (recommended for new domains)
curl -X POST https://api.winnr.app/v1/domains/connect \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domains": ["outreach-acme.com", "mail-acme.com"]
}'
Response:
{
"data": {
"domains": [
{
"domain": "outreach-acme.com",
"domain_id": "dom_abc",
"status": "created",
"nameservers": ["ns1.assigned-ns.example", "ns2.assigned-ns.example"]
},
{
"domain": "mail-acme.com",
"domain_id": "dom_def",
"status": "created",
"nameservers": ["ns1.assigned-ns.example", "ns2.assigned-ns.example"]
}
]
},
"meta": { ... }
}
Use the nameservers values returned for each domain; they are assigned per domain, so don't hardcode them.
At this point, you (or your user) need to update the domain's nameservers at the registrar to point to the Winnr nameservers. This is the one manual step in the flow, unless you use the Cloudflare integration.
Option B: Cloudflare integration (zero manual DNS steps)
curl -X POST https://api.winnr.app/v1/domains/connect \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domains": ["outreach-acme.com"],
"cloudflare_api_token": "cf_token_..."
}'
When you provide a cloudflare_api_token (with Zone:DNS:Edit and Zone:Zone:Edit permissions), Winnr creates the mail records directly in your Cloudflare zone and provisioning starts immediately. No nameserver change. No manual steps. This is the fastest path to production if your domains are already on Cloudflare.
Bulk domain search (optional)
If you want to help users find available domains, use the search endpoints:
# Check availability of up to 100 domains at once
curl -X POST https://api.winnr.app/v1/domains/search-bulk \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domains": ["acme-outreach.com", "acme-mail.com", "acme-sales.com"]
}'
# Or get domain suggestions from keywords
curl "https://api.winnr.app/v1/domains/suggest?keywords=acme" \
-H "Authorization: Bearer $TOKEN"
Step 3: Verify DNS & Provision
After connecting domains and updating nameservers (or using Cloudflare), verify the DNS configuration:
curl -X POST https://api.winnr.app/v1/domains/check-ns \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"domains": ["outreach-acme.com"]}'
Response when verified:
{
"data": {
"domains": [
{
"domain": "outreach-acme.com",
"domain_id": "dom_abc",
"status": "verified",
"verified": true,
"message": "Nameservers verified. Domain queued for provisioning."
}
],
"all_verified": true
},
"meta": { ... }
}
When verified is true, Winnr automatically queues the domain for full provisioning: MX records, DKIM key generation, SPF/DMARC policies, and mail server configuration. For a domain you already own, you can also explicitly trigger setup:
curl -X POST https://api.winnr.app/v1/domains/setup \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"domain": "outreach-acme.com"}'
# Returns: {"data": {"job_id": "job_xyz", "type": "domain_setup", "status": "pending", ...}, "meta": {...}}
Check DNS propagation status at any time:
curl https://api.winnr.app/v1/domains/dom_abc/dns-status \
-H "Authorization: Bearer $TOKEN"
# Returns verification status for NS, MX, SPF, DKIM records
Nameserver changes usually take effect within a few hours, and can take up to 48. The Cloudflare flow skips that wait because there's no NS change. Build your UI to poll /domains/{id}/dns-status and show a progress indicator rather than making users wait.
Step 4: Create Mailboxes
Once a domain is provisioned, you can create mailboxes. A single API call creates production-ready email accounts with full IMAP/SMTP access.
Single mailbox
curl -X POST https://api.winnr.app/v1/email-users \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"username": "sarah",
"domain": "outreach-acme.com",
"name": "Sarah Chen"
}'
Response:
{
"data": {
"job_id": "job_m1",
"status": "pending",
...
},
"meta": { ... }
}
The domain field is the domain name, not its id. If you omit password, a strong one is generated; read it back from GET /v1/email-users/{user_id} once the job completes.
Bulk mailbox creation (up to 500 at once)
This is the endpoint most integrations rely on. Create all of a user's mailboxes in one call:
curl -X POST https://api.winnr.app/v1/email-users/bulk \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domain": "outreach-acme.com",
"users": [
{"username": "sarah", "name": "Sarah Chen"},
{"username": "james", "name": "James Rivera"},
{"username": "alex", "name": "Alex Kim"},
{"username": "maria", "name": "Maria Santos"},
{"username": "david", "name": "David Park"}
]
}'
Response:
{
"data": {
"job_id": "job_bulk_01",
"status": "pending",
"domain": "outreach-acme.com",
"users_count": 5,
"message": "Bulk creation of 5 user(s) queued on outreach-acme.com"
},
"meta": { ... }
}
Python: Full provisioning workflow
Here's a complete Python example that connects a domain, waits for provisioning, and creates mailboxes:
import requests
import time
API = "https://api.winnr.app/v1"
HEADERS = {
"Authorization": "Bearer wnr_acct123_sk_live_...",
"Content-Type": "application/json",
}
def wait_for_job(job_id, timeout=300):
"""Poll job status until completed or failed."""
start = time.time()
while time.time() - start < timeout:
resp = requests.get(f"{API}/jobs/{job_id}", headers=HEADERS)
job = resp.json()["data"]
if job["status"] == "completed":
return job
if job["status"] == "failed":
raise Exception(f"Job failed: {(job.get('error') or {}).get('message')}")
time.sleep(5)
raise TimeoutError(f"Job {job_id} timed out")
# 1. Connect the domain
resp = requests.post(f"{API}/domains/connect", headers=HEADERS, json={
"domains": ["outreach-acme.com"]
})
domain = resp.json()["data"]["domains"][0]
print(f"Domain {domain['domain']} connected. Set NS to: {domain['nameservers']}")
# 2. Wait for DNS verification (after NS change at registrar)
# In production, you'd poll this on a schedule or webhook
verified = False
while not verified:
resp = requests.post(f"{API}/domains/check-ns", headers=HEADERS, json={
"domains": ["outreach-acme.com"]
})
verified = resp.json()["data"].get("all_verified", False)
if not verified:
print("Waiting for DNS propagation...")
time.sleep(60)
# 3. Create mailboxes in bulk
resp = requests.post(f"{API}/email-users/bulk", headers=HEADERS, json={
"domain": "outreach-acme.com",
"users": [
{"username": "sarah", "name": "Sarah Chen"},
{"username": "james", "name": "James Rivera"},
{"username": "alex", "name": "Alex Kim"},
{"username": "maria", "name": "Maria Santos"},
{"username": "david", "name": "David Park"},
]
})
wait_for_job(resp.json()["data"]["job_id"])
# 4. List the domain's mailboxes to verify (note the filter[domain] parameter)
resp = requests.get(f"{API}/email-users", headers=HEADERS, params={
"filter[domain]": "outreach-acme.com"
})
for user in resp.json()["data"]:
print(f" {user['full_address']} - {user['status']}")
Generate usernames with AI
If you want realistic-looking mailbox names without hardcoding them, use the name generation endpoint:
curl -X POST https://api.winnr.app/v1/email-users/generate-names \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"count": 5, "style": "professional"}'
# Returns: {"data": ["sarah.chen", "james.r", "m.santos", "d.park", "alex.kim"], "meta": {...}}
Step 5: Send Email
Once mailboxes are provisioned, you can send email through them via the API. Each mailbox has its own sending identity and reputation.
curl -X POST https://api.winnr.app/v1/email-users/usr_abc/inbox/send \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": "prospect@company.com",
"subject": "Quick question about your Q2 roadmap",
"body": "<p>Hi Jordan,</p><p>I noticed your team just launched...</p>",
"html": true
}'
Response:
{
"data": {
"success": true,
"from": "sarah@outreach-acme.com",
"to": "prospect@company.com",
"subject": "Quick question about your Q2 roadmap",
"message_id": "<abc123@outreach-acme.com>"
},
"meta": { ... }
}
Threading: Reply to conversations
For AI SDR tools and sequencers that need to reply in-thread, use the in_reply_to and references fields:
curl -X POST https://api.winnr.app/v1/email-users/usr_abc/inbox/send \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": "prospect@company.com",
"subject": "Re: Quick question about your Q2 roadmap",
"body": "<p>Thanks for the reply, Jordan! That makes sense...</p>",
"html": true,
"in_reply_to": "<reply-xyz@company.com>",
"references": "<abc123@outreach-acme.com> <reply-xyz@company.com>"
}'
This keeps the reply in the same thread in the recipient's inbox, which matters for natural-looking conversations.
Step 6: Read the Inbox
For AI agents and sequencers, reading replies is just as important as sending. The inbox API gives you full access to each mailbox's incoming messages.
# List inbox messages
curl https://api.winnr.app/v1/email-users/usr_abc/inbox \
-H "Authorization: Bearer $TOKEN"
# Get full message body
curl https://api.winnr.app/v1/inbox/msg_123/body \
-H "Authorization: Bearer $TOKEN"
# List attachments
curl https://api.winnr.app/v1/inbox/msg_123/attachments \
-H "Authorization: Bearer $TOKEN"
# Download a specific attachment (returns presigned S3 URL)
curl https://api.winnr.app/v1/inbox/msg_123/attachments/0 \
-H "Authorization: Bearer $TOKEN"
Python: AI agent reply loop
def check_and_reply(user_id):
"""Check inbox for new replies and process them."""
resp = requests.get(
f"{API}/email-users/{user_id}/inbox",
headers=HEADERS
)
messages = resp.json().get("data", [])
for msg in messages:
if msg.get("is_read"):
continue
# Get the full message body
body_resp = requests.get(
f"{API}/inbox/{msg['uid']}/body",
headers=HEADERS
)
body = body_resp.json()["data"].get("body", "")
# Your AI processes the reply here
ai_response = generate_ai_reply(body)
# Send the reply in-thread
requests.post(
f"{API}/email-users/{user_id}/inbox/send",
headers=HEADERS,
json={
"to": msg["from_email"],
"subject": f"Re: {msg['subject']}",
"body": ai_response,
"html": True,
"in_reply_to": msg.get("message_id"),
"references": msg.get("message_id", ""),
}
)
Monitoring Async Jobs
Domain provisioning and mailbox creation are asynchronous. Every async operation returns a job_id that you can poll for status:
curl https://api.winnr.app/v1/jobs/job_xyz \
-H "Authorization: Bearer $TOKEN"
Response:
{
"data": {
"job_id": "job_xyz",
"type": "domain_setup",
"status": "completed",
"progress": {
"dns_zone": "completed",
"dns_records": "completed"
},
"result": { ... },
"error": null,
"created_at": "2026-03-22T10:00:00Z"
},
"meta": { ... }
}
Job statuses: pending → in_progress → completed or failed. On failed, the error.message field says what went wrong. Domain jobs report per-step progress (step names vary by job); batch jobs report total, completed and failed counts.
| Operation | Job Type |
|---|---|
| Domain setup | domain_setup |
| Mailbox creation (single or bulk) | domain_setup |
| Domain deletion | domain_delete |
| Warming enable / disable | warming_enable / warming_disable |
For production integrations, poll every 5 seconds for the first 30 seconds, then every 15 seconds after that. Or list recent jobs to get a batch view:
curl "https://api.winnr.app/v1/jobs?limit=20" \
-H "Authorization: Bearer $TOKEN"
Integration Best Practices
These patterns lead to the most reliable integrations:
1. Poll jobs, don't assume instant completion. Mailbox creation is async. Always poll /v1/jobs/{id} before treating a mailbox as ready. Assuming instant completion is a common source of integration bugs. Build a job status page or progress indicator in your UI.
2. Warm before sending cold email, then keep volume modest. A freshly provisioned mailbox has zero sending reputation. If your product sends cold email, enable built-in email warming when mailboxes are created and wait at least 2 weeks (4 on a brand-new domain) before campaigns start. After that, send 10 to 20 cold emails per mailbox per day, with total sending (cold plus warming) at about 50 or less. (See built-in warming vs sequencer warmup pools vs standalone warmup tools for details.)
3. Use bulk endpoints for efficiency. Creating 50 mailboxes one at a time means 50 API calls and 50 jobs to track. Creating them with /v1/email-users/bulk means 1 API call and 1 job. The bulk endpoint accepts up to 500 users per request.
4. Check capacity and handle rate limits. Each account has a mailbox allowance from its plan and a domain slot count. Check GET /v1/account/usage before provisioning so a create call doesn't fail on capacity, and back off on 429 responses. Domain slots are free and can be raised in Settings; extra mailboxes are $1 per mailbox per month.
5. Build for domain rotation. For cold email use cases, plan for domain rotation from the start. Domains accumulate sending reputation (both positive and negative). The best integrations provision multiple domains per user and rotate sending across them. When a domain's reputation dips, provision a replacement through the API and move sending to it.
6. Use the Cloudflare flow for zero-touch onboarding. If your users manage DNS through Cloudflare, the cloudflare_api_token parameter on /v1/domains/connect eliminates the manual nameserver step entirely. It removes the wait for a nameserver change to take effect.
7. Store Winnr IDs in your database. Map your internal user/account/campaign objects to Winnr domain_ids and user_ids. This makes it trivial to send through specific mailboxes, check their status, or delete them when a customer churns.
Frequently Asked Questions
What does it cost to provision mailboxes via the API?
API access is included in both Winnr plans. You pay for mailboxes exactly as if you created them in the dashboard: Startup is $69/mo for 50 mailboxes and Enterprise is $189/mo for 200, extra mailboxes are $1 per mailbox per month, and warming is an optional $0.60 per mailbox per month. There are no separate API fees or per-call charges, and billing is monthly with no annual contract. See the pricing page for the full breakdown.
How quickly are mailboxes ready to use after creation?
Mailbox creation is asynchronous: poll the job until it completes. Once provisioned, the mailbox can immediately receive email and send via the API or SMTP. For cold outreach, enable warming and wait at least 2 weeks (4 on a brand-new domain) before sending cold email, then start at 10 to 20 cold emails per mailbox per day. Sending cold email from unwarmed mailboxes on new domains is the fastest way to land in spam.
Can I use IMAP/SMTP directly instead of the API?
Yes. Every mailbox provisioned through the API is a real IMAP/SMTP mailbox. You can connect to it with any email client, send via SMTP from your own application code, or use the Winnr API endpoints for sending and inbox access. The API is the easiest integration path, but SMTP is fully supported if your architecture requires it.
What happens to mailboxes if my users cancel?
You control the lifecycle. Use DELETE /v1/email-users/{id} or DELETE /v1/email-users/bulk to remove mailboxes when a user cancels. Domains can be deleted with DELETE /v1/domains/{id}. If the mailboxes were warming, disable warming too (deleting a mailbox stops its warming and its warming charge from the next cycle).
Is there a limit on how many mailboxes I can create?
Your plan includes 50 (Startup) or 200 (Enterprise) mailboxes, and you can add more at $1 per mailbox per month. Domain slots are free: raise the count yourself in Settings, Subscription. The bulk creation endpoint accepts up to 500 mailboxes per request on one domain. For very large deployments, contact support to plan capacity.
Does the API support DNS authentication (SPF, DKIM, DMARC)?
Yes, automatically. When you provision a domain through the API, Winnr generates DKIM keys, publishes SPF records, and configures DMARC policies without any additional API calls. You can verify the DNS authentication status at any time via GET /v1/domains/{id}/dns-status. This is one of the key advantages of using Winnr vs managing your own infrastructure: authentication is always correct and always up to date.
How do I handle errors and retries?
The API returns standard HTTP status codes: 200/201 for success, 400 for validation errors, 401/403 for auth issues, 429 for rate limits, and 500 for server errors. For async jobs that fail, the job response includes a message field describing the failure. We recommend implementing exponential backoff for 429 and 500 responses, and logging the message field from failed jobs for debugging. The full API docs document every error code and response schema.
What programming languages are supported?
The Winnr API is a standard REST API that works with any programming language that can make HTTP requests. This guide shows examples in cURL and Python, but the API works identically with JavaScript/Node.js, Ruby, Go, Java, PHP, Rust, or any other language. No language-specific SDK is required. Make HTTP calls with your preferred HTTP client library.
How is this different from Amazon SES or SendGrid?
SES and SendGrid are transactional email services: they send email through their infrastructure using your domain. Winnr provisions dedicated mailboxes with their own IMAP inboxes, individual sending reputations, and full inbox access (read, reply, thread). Each mailbox is a real email account, not a sending API. This matters for cold email, AI SDR tools, and any use case where you need to receive replies, manage conversations, and build per-mailbox sending reputation.
Winnr also has an open source MCP server that lets AI assistants (Claude, Cursor, Windsurf) call the same API endpoints through natural language. If you're building an AI SDR or agent-driven workflow, the MCP server gives your AI 55 tools for domains, mailboxes, warming, and inbox, with no API integration code needed. Learn more.
Ready to integrate? The full API reference documents every endpoint, request schema, response format, and error code. Creating a Winnr account needs no card; generate an API token and make your first call, then pick a plan when you're ready to provision mailboxes on SMTP infrastructure built for cold email.
Related: building an AI SDR pipeline with Claude Code and Winnr and buying domains, provisioning inboxes and uploading to Instantly with the API.