# Warmerly documentation > Warmerly is an email warmup and cold-outreach platform: connect mailboxes, warm them up automatically, find and verify leads, and run multi-step email campaigns. This is its complete product documentation and REST API reference. - API base URL: https://app.warmerly.com/api/v1 (paths in the reference are written without the /api/v1 prefix) - Authentication: send your key in an `X-Api-Key` header; most endpoints also need `X-Project-Id` (see https://docs.warmerly.com/authentication). Create keys at https://app.warmerly.com/settings/api-keys. - Errors and rate limits: https://docs.warmerly.com/errors - AI assistants can also act on a Warmerly workspace directly through the MCP server at https://app.warmerly.com/api/mcp (see https://docs.warmerly.com/ai). --- # Warmerly Docs The official documentation for [Warmerly](https://warmerly.com), the email warmup and cold outreach platform (not to be confused with Warmly.ai). It covers setting up and using the product and the full REST API. New to Warmerly? Start with [how warmup works](https://docs.warmerly.com/how-warmup-works), [connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection), the [FAQ](https://docs.warmerly.com/faq) and [troubleshooting](https://docs.warmerly.com/troubleshooting). Setting up DNS? See [SPF and DMARC](https://docs.warmerly.com/guides/spf-dmarc) and [DKIM](https://docs.warmerly.com/guides/dkim). ## The Warmerly API The Warmerly API lets you connect mailboxes, run email warmup, send campaigns, verify addresses, find emails, and manage your workspace programmatically, the same functionality available in the [dashboard](https://app.warmerly.com/login), exposed over HTTP. > **Using an AI assistant?** The whole documentation, API reference included, is available as > one Markdown file at [docs.warmerly.com/llms-full.txt](https://docs.warmerly.com/llms-full.txt) > (index: [/llms.txt](https://docs.warmerly.com/llms.txt)). See [Use with AI](https://docs.warmerly.com/ai#documentation-for-llms). ## Base URL ``` https://app.warmerly.com/api/v1 ``` ## Quick example ```bash curl https://app.warmerly.com/api/v1/accounts \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" ``` ## Not here for the API? Most questions are not API questions. These pages cover the product itself: - [FAQ](https://docs.warmerly.com/faq) - the short answers to what people ask most - [How warmup works](https://docs.warmerly.com/how-warmup-works) - the warmup network, the ramp, and why warmup never emails your prospects - [How our email infrastructure works](https://docs.warmerly.com/infrastructure) - how sending is kept safe: separate lanes, how a new sending IP earns volume, and what slows down automatically - [Plans, limits and allowances](https://docs.warmerly.com/plans-and-limits) - what each plan includes and how limits behave - [Troubleshooting](https://docs.warmerly.com/troubleshooting) - DKIM false alarms, Microsoft 365 SMTP errors, campaigns that will not send - [Use with AI (MCP)](https://docs.warmerly.com/ai) - connect Claude, ChatGPT, Claude Code or Cursor to your workspace - [All DNS records](https://docs.warmerly.com/guides/dns-records) - MX, SPF, DKIM, DMARC and tracking, in one checklist - [Guides](https://docs.warmerly.com/guides) - step-by-step DNS and mailbox setup, written for non-developers ## API resources See [Authentication](https://docs.warmerly.com/authentication) for how to get an API key and project ID, then jump into the resource you need: - [Accounts](https://docs.warmerly.com/accounts): connect and manage mailboxes - [Campaigns](https://docs.warmerly.com/campaigns): outbound email and LinkedIn sequences - [Warmup](https://docs.warmerly.com/warmup): warmup health, stats, and trends - [Verify](https://docs.warmerly.com/verify): single and bulk email verification - [Email Finder](https://docs.warmerly.com/email-finder): find and enrich email addresses - [Leads](https://docs.warmerly.com/leads): search, export, and push leads from Warmerly's company database - [Inbox](https://docs.warmerly.com/inbox): unified inbox, threads, and replies - [Suppression](https://docs.warmerly.com/suppression): addresses that must never be sent to - [Webhooks](https://docs.warmerly.com/webhooks): subscribe to mailbox health events - [Workspaces & Projects](https://docs.warmerly.com/workspaces): multi-tenant workspace/project management - [API Keys](https://docs.warmerly.com/keys): create and revoke keys - [Usage & Limits](https://docs.warmerly.com/usage): monthly allowances and plan capacity in one call ## Conventions - All request/response bodies are JSON. - Timestamps are ISO 8601 strings in UTC. - Resource IDs are UUIDs. - Errors return a JSON body of the shape `{ "error": { "code": "...", "message": "..." } }` with a matching HTTP status code (`400`, `401`, `403`, `404`, `409`, `429`, `500`), see [Errors & Rate Limits](https://docs.warmerly.com/errors) for the full error-code table and every rate limit that applies. - See the [API Changelog](https://docs.warmerly.com/changelog) for what's changed and the deprecation policy. ## What's not documented here This API reference deliberately excludes: - **Everything under `/api/v1/admin/*`.** These routes back the internal Warmerly admin panel (workspace impersonation, billing overrides, platform-wide stats, support inbox, and similar). They require staff-only session auth, not an API key, they can't be called with the credentials this docs site describes, and exposing their shapes publicly would leak internal operational detail for no customer benefit. - **Inbound provider webhooks** (`/api/v1/webhooks/resend-inbound`, `/api/v1/webhooks/unipile`). These receive signed callbacks from Warmerly's own infrastructure providers (inbound mail, LinkedIn/WhatsApp, and similar), and they're not something a customer integration calls or points anywhere. The customer-facing webhook feature is [outbound subscriptions](https://docs.warmerly.com/webhooks), where Warmerly calls a URL *you* provide. - **OAuth callback routes** (`/api/v1/oauth/*` and similar). These exist to complete browser-based OAuth redirect flows initiated from the dashboard; there's no way to drive them directly from an API integration. - **Routes with no stable, versioned contract of their own**: internal dashboard plumbing like `/api/v1/dashboard/overview`, `/api/v1/onboarding/*`, and `/api/v1/tools/*` are implementation details of the web app's own UI and may change shape without notice, unlike the endpoints documented in this reference. --- # Authentication Every request to the Warmerly API is authenticated with an API key, sent as the `X-Api-Key` header. **API access is an Agency-plan feature.** Without Agency, creating or listing keys, and any request made with a key, returns `403 agency_plan_required`. Upgrade at [warmerly.com/pricing](https://warmerly.com/pricing). ## Ways to authenticate | Method | Used by | Credential | Plan | | --- | --- | --- | --- | | API key | Your own code, scripts and automation tools | `X-Api-Key: wmv_...` header | Agency | | Signed-in session | The Warmerly dashboard in your browser | Session cookie | Any | | Mobile session | The Warmerly Android app | `Authorization: Bearer ` | Any | | OAuth connection | AI assistants such as Claude, ChatGPT and Cursor, through the [MCP server](https://docs.warmerly.com/ai) | Access token starting `wm_at_` | Any | | Transactional sending key | The [transactional email](https://docs.warmerly.com/transactional) API | `Authorization: Bearer wm_tx_...` or `X-Api-Key: wm_tx_...` | Transactional plan | For your own integrations use an API key. The session cookie and mobile token belong to a signed-in person and are not meant for scripts. The two key types are not interchangeable: `wmv_` keys are refused by the transactional send API, and `wm_tx_` keys are refused everywhere else. ## Getting a key 1. Sign in to [app.warmerly.com](https://app.warmerly.com/login). 2. Go to **Settings > Platform API keys**. On a plan below Agency this page shows an upgrade prompt instead of the form. 3. Enter a **Key name**, click **Create key**, and copy the secret shown. It is only displayed once and cannot be retrieved again. If you lose it, revoke the key and create a new one. Keys are prefixed `wmv_` and are scoped to your user account (they can access every workspace/project you're a member of, subject to the project you select via `X-Project-Id`). You can also create keys programmatically, see [API Keys](https://docs.warmerly.com/keys). A key carries your full access. There are no per-endpoint scopes and no read-only keys, so a key can do whatever you can do in the workspaces you belong to. Warmerly stores only a SHA-256 hash of the key, which is why the secret cannot be shown again. Each user can hold up to 10 active keys. ## Required headers | Header | Required | Description | | --- | --- | --- | | `X-Api-Key` | Always | Your API key secret. | | `X-Project-Id` | Most endpoints | The UUID of the project to operate on (mailboxes, campaigns, and inbox data all belong to a project). Find it in the dashboard URL or via the [Workspaces & Projects](https://docs.warmerly.com/workspaces) endpoints. | | `X-Workspace-Id` | Optional | Which workspace a **workspace-scoped** endpoint (suppression, usage, billing, channel limits, inbox-wide reads) should act in. Omit it and the call uses your account's currently active workspace, which for a key that never touches the dashboard means the one selected there, not necessarily the one you meant. If you work across several workspaces, send it explicitly on every workspace-scoped call. | ```bash curl https://app.warmerly.com/api/v1/accounts \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" ``` Endpoints that aren't project-scoped (e.g. listing your workspaces, managing API keys) only need `X-Api-Key`. There are three scopes, and mixing them up is the most common integration mistake: | Scope | Identified by | Examples | | --- | --- | --- | | Account | the key itself | `/keys`, `/workspaces`, `/projects`, `/alerts` | | Workspace | `X-Workspace-Id`, else your active workspace | `/suppression`, `/usage/quotas`, `/billing/me`, `/accounts/limits`, `/inbox/*` | | Project | `X-Project-Id` (required) | `/accounts`, `/campaigns`, `/email-finder/*` | Campaign-scoped endpoints are the exception that needs neither header: `/campaigns/{id}/…` resolves access from the campaign id in the URL, so passing a mismatched `X-Project-Id` changes nothing. ## Which plan is checked A key has no workspace of its own, so Warmerly checks the plan of the workspace the request acts on: the project in `X-Project-Id` if you send one and you are a member of its workspace, otherwise the workspace in `X-Workspace-Id`, otherwise your own workspace. Naming a workspace never grants anything. You can only use the plan of a workspace you already belong to. If that workspace is not on Agency (for example after a downgrade), requests return `403 agency_plan_required`. The key is not revoked: it works again after you upgrade. The plan check is cached for 60 seconds, so a downgrade or an upgrade can take up to a minute to show. A suspended account gets `403 account_suspended` on every request, including ones made with a key. ## Rate limits Each key has its own per-minute rate limit (default 60 requests/minute, configurable per key up to 120). Exceeding it returns `429 too_many_requests`. A few endpoints layer an additional, tighter limit on top of this. See [Errors & Rate Limits](https://docs.warmerly.com/errors) for the full picture, including the exact response shape and per-endpoint limits. The per-key limit is a fixed window per calendar minute (UTC). Each request counts toward the current minute, and once the count passes the key's limit every further request in that minute returns: ```json { "error": { "code": "too_many_requests", "message": "rate_limit_exceeded", "details": null } } ``` Responses carry no `Retry-After` header, so wait for the next minute to begin before retrying, and spread bulk jobs out instead of sending them in a burst. You choose a key's limit when you create it with `rateLimitPerMin` (1 to 120, default 60); the dashboard form uses the default. Running out of a monthly allowance (verifications, lead exports, lookups) is a different failure and returns `402`, not `429`. ## Authenticating AI assistants (MCP) AI assistants do not use API keys. The MCP server at `https://app.warmerly.com/api/mcp` uses OAuth 2.1 with PKCE (S256 only), so you approve a connection once on a consent screen and never copy a secret. Each connection is scoped to one signed-in user's one workspace, and it is available on every plan including Free. - Access tokens last 1 hour. Refresh tokens last 30 days and rotate each time they are used. - Tool calls are limited to 60 per minute per connection, and tools that send email to a real person have a tighter limit. - To see or cut off a connection, open **Settings > Connected apps** and revoke it. Removing a member from a workspace also ends their connections to it. Setup steps for each assistant are in [Use Warmerly with AI (MCP)](https://docs.warmerly.com/ai), and the approval screen is explained in [How do I connect, check or revoke an AI app?](https://docs.warmerly.com/help/manage-connected-ai-apps). ## Revoking a key Revoke a key any time from **Settings > Platform API keys** with the **Revoke** button on its row, or with [`DELETE /keys/{id}`](https://docs.warmerly.com/keys#revoke-a-key). Revoked keys fail every request immediately with `401 unauthorized`, there is no grace period. ## Rotating a key Rotate keys on a schedule, and immediately if one may have leaked. Because you can hold 10 active keys, rotation needs no downtime: 1. Create a new key and name it after the integration it replaces. 2. Deploy the new key to your application or secret store. 3. Check the old key's `lastUsedAt` in [`GET /keys`](https://docs.warmerly.com/keys#list-keys), or the last-used time on the settings page. When it stops advancing, nothing is using it any more. 4. Revoke the old key. Revocation is immediate and cannot be undone. Key creation and revocation are recorded in the workspace audit log as `api_key.created` and `api_key.revoked`. See [What is the audit log?](https://docs.warmerly.com/help/audit-log). ## Keeping keys safe - Keep keys in environment variables or a secrets manager, never in source control, front-end code or a mobile app. Anyone holding a key can act as you. - Use one key per integration, named after it, so you can revoke one without breaking the others. - Call the API from a server, not from a browser page, where visitors could read the key. - If a key leaks, revoke it first and investigate second. - Revoke keys you no longer use. Revoking is always allowed, even after a downgrade. ## Errors An invalid or revoked key returns `401`: ```json { "error": { "code": "unauthorized", "message": "unauthorized", "details": null } } ``` A missing or malformed `X-Project-Id` on a project-scoped endpoint returns `400`: ```json { "error": { "code": "bad_request", "message": "missing X-Project-Id header", "details": null } } ``` | Status | `error.code` | Cause | | --- | --- | --- | | `401` | `unauthorized` | Key missing, unknown or revoked. | | `403` | `agency_plan_required` | The workspace the request acts on is not on Agency. | | `403` | `account_suspended` | The account is suspended. | | `400` | `bad_request` | `X-Project-Id` missing or not a valid UUID. | | `429` | `too_many_requests` | The key's per-minute limit was exceeded. | The full list is in [Errors & Rate Limits](https://docs.warmerly.com/errors). ## Common questions **Why do I get `403 agency_plan_required` with a valid key?** The workspace the request acts on is not on the Agency plan. Check the `X-Project-Id` and `X-Workspace-Id` you are sending. **Can I see my key again?** No. Revoke it and create a new one. **Can I limit a key to certain endpoints?** No. Keys have no scopes and carry your access. **Does one key work across workspaces?** Yes, for every workspace you are a member of, as long as the workspace you target is on Agency. Send `X-Project-Id` or `X-Workspace-Id` to choose. **How is this different from the transactional sending keys?** Sending keys (`wm_tx_`) are for the transactional email API and belong to one workspace. See [Transactional email](https://docs.warmerly.com/transactional). --- # Getting started with Warmerly: from signup to your first send This is the whole path in order, with a link for each step. You do not have to finish it in one sitting: you can launch on the day you sign up, and warmup keeps working while you do the rest. The **Dashboard** also shows a "Get started with Warmerly" card that ticks off the mailbox and campaign steps for you. ## 1. Create your account - Go to [warmerly.com](https://warmerly.com) and sign up with your email and a password, or with Google. There is no card and no trial clock on the Free plan. - If you signed up with email, confirm your address from the email we send. Some things wait on this, for example your account's security and notification emails. - The first time in, a short setup wizard asks about you (**Profile**), what you want to do (**Goal**), who you want to reach (**Audience**, only if you chose outreach), your **Plan** and a **Mailbox**. You can skip the questions and connect a mailbox later with **I'll do this later**. The plan step is not skippable, but its one-click **Free** option is the way through. - Signing up to send your own app's email? Choose "Send app emails from my code" and follow [Getting started with transactional email](https://docs.warmerly.com/help/transactional-email-getting-started) instead. ## 2. Meet your free mailbox Every new account gets one free mailbox, already warming up. Find it on **Accounts** with the **Free gift** badge. It needs no domain and no DNS, and it does not count against your plan. It warms up and can be used for replies and tests, but it does not send campaigns. Details: [How do I get a free sending mailbox?](https://docs.warmerly.com/help/free-sending-mailbox). ## 3. Connect your own mailbox To send campaigns, connect the address you will send from. Go to **Accounts** and click **Add**. - **Microsoft 365 or Outlook:** one-click sign-in. - **Gmail or Google Workspace:** a Google app password. See [Connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection). - **Any other provider:** IMAP and SMTP details. - **No mailbox yet, or want fewer moving parts:** let Warmerly host one with OneMail, which sends to verified addresses. See [OneMail](https://docs.warmerly.com/help/onemail-mailboxes). **Warmup starts automatically as soon as it is connected.** Keep it on, before and after you start sending. See [How warmup works](https://docs.warmerly.com/how-warmup-works). If a mailbox later needs attention, see [Reconnect a mailbox](https://docs.warmerly.com/help/reconnect-mailbox). ## 4. Set up your domain's DNS Email providers trust a domain that proves it sent the message. On your domain's DNS, publish: - **DKIM:** [Setting up DKIM](https://docs.warmerly.com/guides/dkim) (with click-by-click pages for Cloudflare, GoDaddy, IONOS and Namecheap). - **SPF and DMARC:** [SPF & DMARC records](https://docs.warmerly.com/guides/spf-dmarc). - Optional, later: a [custom tracking domain](https://docs.warmerly.com/guides/custom-tracking-domain). If you used OneMail, this is done for you. ## 5. Check that it is working Open **Dashboard** and read the health score and inbox placement. A new mailbox shows a first-run panel until warmup has sent something, which is normal: see [Dashboard overview](https://docs.warmerly.com/help/dashboard-overview). For a direct answer on whether mail reaches the inbox, run a placement test from **Accounts**, open the mailbox, then the **Health** tab and **Run new test**. A mailbox is fully warm after about two weeks, longer on a brand-new domain. ## 6. Get your leads You can do this while warmup runs. - **Find leads** (sidebar **Prospecting**): search Warmerly's database and add leads to a campaign. - **Import a CSV** into a campaign: [How do I import leads from a CSV?](https://docs.warmerly.com/help/import-leads-csv) - **Email finder** and **Email verification** (also under **Prospecting**) find and check addresses before you send. They use monthly allowances: see [Plans & limits](https://docs.warmerly.com/plans-and-limits). ## 7. Launch your first campaign Open **Campaigns > New campaign** and follow **Audience**, **Sequence** and **Launch**. You do not have to wait for warmup to finish: campaigns on young mailboxes start with a small daily volume that climbs. Campaigns need your own connected mailbox or a OneMail mailbox, not the free one. Read the "Ready to launch?" checks before clicking **Launch now**. Full steps: [How do I launch my first campaign?](https://docs.warmerly.com/help/launch-first-campaign). ## 8. Handle the replies Replies from every mailbox arrive in **Inbox**, auto-sorted as leads, not relevant or spam. To be told the moment a prospect answers, install the [Android app](https://docs.warmerly.com/help/android-app): it sends a push notification for genuine replies and lets you answer from the notification. ## 9. Know your limits **Settings > Usage & limits** shows every monthly allowance and plan limit. Nothing is ever deleted when you reach one. If you need more, **Settings > Billing** is where you change plan, and you can top up some allowances with credits. See [Plans & limits](https://docs.warmerly.com/plans-and-limits) and [Cancel or change plan](https://docs.warmerly.com/help/cancel-or-change-plan). ## 10. Optional extras - **Invite teammates:** **Settings > Team**. - **More than one brand or client:** **Settings > Workspaces**. See [Workspaces](https://docs.warmerly.com/workspaces). - **Use Warmerly from your AI assistant:** [Connected apps](https://docs.warmerly.com/help/manage-connected-ai-apps). - **Use the API:** [How do I use Warmerly with an API?](https://docs.warmerly.com/help/use-the-api). API access needs the Agency plan. - **Book a free 15-minute setup call:** **Settings > Book a 1:1 setup call**. ## When you are stuck - **Ask Warmi** in the chat button at the bottom right. It can look at your own account when you are signed in, and hand you to a person. See [Warmi](https://docs.warmerly.com/help/warmi-support-assistant). - **Something looks down:** [the status page](https://docs.warmerly.com/help/status-page). - **Words you do not know:** [Glossary](https://docs.warmerly.com/help/glossary). - **A specific problem:** [Troubleshooting](https://docs.warmerly.com/troubleshooting) and the [FAQ](https://docs.warmerly.com/faq). ## Common problems **I skipped the wizard, where do I go now?** Open **Dashboard**. The "Get started" card has the same two steps. Or go straight to **Accounts** and **Campaigns**. **Nothing has sent yet.** A new mailbox starts slowly on purpose. If a campaign is live and nothing is going out after a while, work through [A campaign is not sending](https://docs.warmerly.com/troubleshooting#a-campaign-is-not-sending). **I did not get the confirmation email.** Check spam. If it still does not arrive, ask Warmi or email support@warmerly.com. ## Related - [Help Center](https://docs.warmerly.com/help) - [Dashboard overview](https://docs.warmerly.com/help/dashboard-overview) - [Where do I see what's new?](https://docs.warmerly.com/help/whats-new) --- # Glossary of Warmerly terms What the words in the Warmerly app mean. For general email terms (SPF, DKIM, DMARC, sender reputation) there is also the [deliverability glossary](https://warmerly.com/glossary) on warmerly.com. Plan prices and allowance numbers are never listed here: see [Plans & limits](https://docs.warmerly.com/plans-and-limits). ## Mailboxes and warmup ### Mailbox An email address Warmerly sends from and reads replies from. You either connect one you already have (Gmail or Google Workspace with an app password, Microsoft 365 or Outlook with one-click sign-in, or any provider over IMAP and SMTP), or Warmerly hosts one for you (OneMail). Mailboxes live under **Accounts**. See [Connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection). ### Account On the **Accounts** page, an "account" is any sending identity: a mailbox, a LinkedIn account or a WhatsApp number. (In the API docs and some code paths a mailbox is called an "email account".) ### OneMail Mailboxes and domains that Warmerly hosts for you, with the DNS and warmup handled. You can buy a new domain, bring one you own, or add mailboxes to a domain you have. A OneMail mailbox is billed per mailbox and never uses your plan's mailbox limit. See [OneMail](https://docs.warmerly.com/help/onemail-mailboxes). ### Free mailbox (also called the sandbox mailbox) The mailbox every new account gets at signup, already warming up. It shows a **Free gift** badge on **Accounts**, uses no plan slot, and needs no DNS. It warms up and can be used for replies and tests, but it does not send campaigns. Inside Warmerly and in some answers you may see it called the "sandbox" or "free trial" mailbox. See [How do I get a free sending mailbox?](https://docs.warmerly.com/help/free-sending-mailbox). ### Ready-warmed mailbox A OneMail mailbox that is already warm when you buy it, when available. See [OneMail](https://docs.warmerly.com/help/onemail-mailboxes). ### Warmup Background activity that builds a mailbox's sending reputation: your mailbox exchanges ordinary messages with other mailboxes in Warmerly's warmup network, and both sides open and reply. Warmup **never emails your prospects**. The marketing name for the engine is Warmflow. See [How warmup works](https://docs.warmerly.com/how-warmup-works). ### Ramp Starting small and increasing volume over time. There are two: - **The warmup ramp:** a mailbox's daily warmup volume rises gradually toward its limit. When you connect a mailbox you can choose how quickly (Safe, Balanced or Faster in the Android setup). - **The campaign volume ramp:** a campaign whose mailboxes have had under 14 days of warmup starts with a small number of emails per mailbox per day and climbs, which makes launching on day one safe. You can turn it off in the campaign's **Settings** tab. ### Daily limit The most emails a mailbox will send per day. It is shared across every campaign that mailbox sends for. See [Troubleshooting](https://docs.warmerly.com/troubleshooting#a-campaign-is-not-sending). ### Health score A number from 0 to 100 for how likely a mailbox's email is to reach the inbox instead of spam. Statuses you will see next to it: **Healthy** (sending well), **Warming** (still building trust), **At Risk** (warning signs, may need action) and **Paused** (not sending right now). See [Dashboard overview](https://docs.warmerly.com/help/dashboard-overview). ### Paused, and "campaign sending paused" These are different. A **paused** mailbox is stopped for both warmup and campaigns and needs attention (for example it needs reconnecting). A mailbox whose **campaign sending is paused** because of reputation is out of campaigns only: warmup keeps running and campaign sending returns automatically once it is healthy again; if the whole workspace was restricted, our team may also take a look. See [Why did my sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused) and [Troubleshooting](https://docs.warmerly.com/troubleshooting#a-mailbox-is-paused-or-shows-as-unreachable). ### Placement test A test that sends real probe emails from a mailbox to seed addresses at several providers and reports whether each landed in the inbox, promotions or spam. Run it from **Accounts**, open the mailbox, then the **Health** tab and **Run new test**. Each test uses one of your monthly placement tests. ### Tracking domain Your own web address used for open and click tracking links in campaign emails, instead of Warmerly's. See [Custom tracking domain](https://docs.warmerly.com/guides/custom-tracking-domain). ## Campaigns and leads ### Campaign A sequence of emails sent to a list of leads from the mailboxes you choose, on a schedule. Built under **Campaigns > New campaign**: **Audience**, **Sequence**, **Launch**. See [How do I launch my first campaign?](https://docs.warmerly.com/help/launch-first-campaign). ### Lead A person you might email, with their address and company details. Leads belong to a campaign. Find them with **Find leads**, import a CSV, or add them by API. ### Sequence and merge tag The **sequence** is the series of emails a campaign sends. A **merge tag** (also called a variable), such as `{{firstName}}`, is filled in from each lead's data when the email is sent. ### Sender A mailbox chosen to send a campaign. Emails are spread across the senders you pick. ### Suppression list (shown as "Do not contact") Addresses Warmerly must never email from your workspace: hard bounces, spam complaints, unsubscribes and ones you add. Found at **Settings > Do not contact**. Campaigns and replies skip these addresses automatically. See [Suppression API](https://docs.warmerly.com/suppression). ### Verification, and Email finder **Email verification** (sidebar **Prospecting > Email verification**) checks whether an address is likely deliverable before you send. **Email finder** looks up an address for a person or company. Both use monthly allowances. ### Website summary and Data library **Website summary** turns a web page into short factual research for personalising outreach. The **Data library** is where results from these tools are saved for reuse and export. ### Warmerly Link The name of the LinkedIn side of Warmerly (sidebar **Outreach > Warmerly Link**): LinkedIn warmup and outreach. It is sold per connected LinkedIn account. See [Plans & limits](https://docs.warmerly.com/plans-and-limits). ### Inbox **Inbox** in the sidebar collects replies from every mailbox in one place. Replies are auto-categorised as lead, not relevant or spam. ## Workspaces, plans and limits ### Workspace The top-level container for your account: it owns the plan, the billing, the team members and everything inside it. You can belong to several. Managed under **Settings > Workspaces** and **Settings > Team**. On the Agency plan, client workspaces share the Agency workspace's allowances. See [Workspaces](https://docs.warmerly.com/workspaces). ### Project A subdivision inside a workspace for a client or brand, with its own mailboxes, campaigns and inbox. If you only run one brand you can ignore projects. See [Workspaces](https://docs.warmerly.com/workspaces#projects). ### Slot A unit you buy on top of your plan for one extra account of a kind: a **Warmerly Link slot** for each connected LinkedIn account, and a **WhatsApp slot** for each extra WhatsApp number beyond what your plan includes. A "mailbox slot" is informal for one of the mailboxes your plan lets you connect. ### Monthly allowance A monthly meter that resets on the 1st and does not roll over: verifications, email lookups, LinkedIn lookups, lead exports, placement tests, AI credits and Free's campaign sends. ### Capacity limit A live count with no reset, such as mailboxes, active campaigns and active prospects. Disconnect a mailbox and the slot is free at once. ### Credit The currency for AI actions and for top-ups. Your plan includes a monthly amount of AI credits. You can also buy credit packs, which never expire and are spent after the monthly amount. Credits can buy a block of extra verifications, lookups, lead exports or placement tests when you run out mid-month, and nothing is ever bought automatically. See **Settings > Usage & limits**. ### Grace period and billing lock If a workspace ends up over its plan, a countdown banner gives it a grace period, during which everything keeps working. A **billing lock** is the screen that blocks the dashboard when there is no plan, a payment is overdue, or the grace period has ended. Warmup and campaign sending pause while it lasts, and nothing is deleted. See [Plans & limits](https://docs.warmerly.com/plans-and-limits#billing-lock). ## Assistants and developers ### Warmi Warmerly's AI support assistant, in the chat button on every page. See [Warmi](https://docs.warmerly.com/help/warmi-support-assistant). ### Connected app, and MCP An AI assistant (Claude, ChatGPT, Cursor and others) you have allowed into one workspace through the Model Context Protocol (MCP). Managed under **Settings > Connected apps**. See [Use Warmerly with AI](https://docs.warmerly.com/ai) and [connected apps](https://docs.warmerly.com/help/manage-connected-ai-apps). ### Platform API key and Sending key A **Platform API key** (**Settings > Platform API keys**) is for the Warmerly API and needs the Agency plan. A **Sending key** (**Transactional email > Sending keys**) works only for transactional email. Neither works in place of the other. See [Authentication](https://docs.warmerly.com/authentication). ### Transactional email Email your own app sends to its users, such as password resets and receipts, through a separate product with its own domains, keys and billing. See [Getting started with transactional email](https://docs.warmerly.com/help/transactional-email-getting-started). ### Webhook A web address of yours that Warmerly calls when something happens, such as a mailbox health event. Set up under **Settings > Webhooks**. See [Webhooks](https://docs.warmerly.com/webhooks). ### Audit log A record of recent activity by your team and by connected apps, under **Settings > Audit log**. ## Related - [Getting started checklist](https://docs.warmerly.com/help/getting-started-checklist) - [Frequently asked questions](https://docs.warmerly.com/faq) --- # Help Center Short, step-by-step answers to the questions Warmerly customers ask most. Each one starts with the answer, then walks you through it. Can't find yours? Ask Warmi in the chat widget at the bottom right of the app and these docs. ## Getting started | Question | In short | | --- | --- | | [How do I get a free sending mailbox?](https://docs.warmerly.com/help/free-sending-mailbox) | Every new account gets one, already warming up. | | [What is OneMail, and can I buy or bring a domain?](https://docs.warmerly.com/help/onemail-mailboxes) | Mailboxes we host: buy a domain or connect yours, DNS and warmup handled. | | [How do I connect a Gmail, Google Workspace or Outlook mailbox?](https://docs.warmerly.com/guides/mailbox-connection) | One-click sign-in for Microsoft, an app password for Google. | | [How long does email warmup take?](https://docs.warmerly.com/how-warmup-works) | About two weeks, but you can launch on day one. | | [How do I launch my first campaign?](https://docs.warmerly.com/help/launch-first-campaign) | Campaigns > New campaign: audience, sequence, launch. | | [How do I import leads from a CSV?](https://docs.warmerly.com/help/import-leads-csv) | A campaign's Audience tab > Import leads. | ## Mailboxes and deliverability | Question | In short | | --- | --- | | [Why did my mailbox disconnect, and how do I reconnect it?](https://docs.warmerly.com/help/reconnect-mailbox) | Warmerly can no longer sign in. Open it and click Reconnect. | | [What DNS records do I need?](https://docs.warmerly.com/guides/dns-records) | MX, SPF, DKIM and DMARC, plus an optional tracking CNAME. | | [How do I set up DKIM?](https://docs.warmerly.com/guides/dkim) | Get the record from your email provider and add it to your DNS. | | [How do I set up SPF and DMARC?](https://docs.warmerly.com/guides/spf-dmarc) | Two TXT records that tell providers your mail really is from you. | | [How do I use a custom tracking domain?](https://docs.warmerly.com/guides/custom-tracking-domain) | A CNAME on your own domain for tracked links. | ## Plans, billing and the API | Question | In short | | --- | --- | | [How do I cancel or change my plan?](https://docs.warmerly.com/help/cancel-or-change-plan) | Settings > Billing. Cancel through Manage billing. | | [What does each plan include?](https://docs.warmerly.com/plans-and-limits) | Free, Starter, Growth and Agency, side by side. | | [How do I use Warmerly with an API?](https://docs.warmerly.com/help/use-the-api) | Agency plan (or its trial): create a key, send it as X-Api-Key. | | [Can I use Warmerly from ChatGPT or Claude?](https://docs.warmerly.com/ai) | Yes, through the Warmerly MCP server. | ## Still stuck? - [FAQ](https://docs.warmerly.com/faq): quick answers on warmup, billing, mailboxes and campaigns - [Troubleshooting](https://docs.warmerly.com/troubleshooting): DKIM false alarms, Microsoft 365 errors, campaigns not sending, placement tests - [Guides](https://docs.warmerly.com/guides): DNS and mailbox setup, click by click ## Start here - [Getting started with Warmerly: from signup to your first send](https://docs.warmerly.com/help/getting-started-checklist) - [Glossary of Warmerly terms](https://docs.warmerly.com/help/glossary) ## Prospecting - [How do I find leads with Find leads?](https://docs.warmerly.com/help/find-leads) - [How do I find someone's email address?](https://docs.warmerly.com/help/email-finder) - [How do I check whether an email address is valid?](https://docs.warmerly.com/help/email-verification) - [How do I summarize a prospect's website?](https://docs.warmerly.com/help/website-summary) - [What is the Data library and where do my bulk results go?](https://docs.warmerly.com/help/data-library) - [How do lead exports, lookups and verifications use my allowance?](https://docs.warmerly.com/help/prospecting-allowances) ## Campaigns & inbox - [How do I write an email sequence for a campaign?](https://docs.warmerly.com/help/email-sequences) - [What merge tags and custom variables can I use in my emails?](https://docs.warmerly.com/help/merge-tags) - [How do I personalise every email with the AI opener?](https://docs.warmerly.com/help/ai-opener) - [How do I A/B test a subject line or email in a campaign?](https://docs.warmerly.com/help/ab-test-email-copy) - [How do I see who has been contacted in a campaign?](https://docs.warmerly.com/help/campaign-audience) - [What do the campaign statuses mean (draft, sending, paused, completed)?](https://docs.warmerly.com/help/campaign-statuses) - [Why does my campaign send fewer emails than my daily limit?](https://docs.warmerly.com/help/campaign-sending-schedule) - [Can I launch a campaign before my mailbox has finished warming up?](https://docs.warmerly.com/help/launch-before-warmup-finishes) - [What stops a campaign sequence for a lead?](https://docs.warmerly.com/help/what-stops-a-sequence) - [How do open and click tracking work in a campaign?](https://docs.warmerly.com/help/open-and-click-tracking) - [How do unsubscribe links work in campaign emails?](https://docs.warmerly.com/help/unsubscribe-links) - [What does the Warmi advice on my campaign mean?](https://docs.warmerly.com/help/campaign-advice) - [How does the Inbox work? (replies, categories and answering leads)](https://docs.warmerly.com/help/inbox) ## Deliverability - [What do my mailbox's health score and status mean?](https://docs.warmerly.com/help/mailbox-health) - [How do I read the domain health card?](https://docs.warmerly.com/help/domain-health-card) - [How do inbox placement tests work?](https://docs.warmerly.com/help/placement-tests) - [What if my domain or IP is on a blocklist?](https://docs.warmerly.com/help/blocklisted) - [Why did my sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused) - [My mailbox won't connect: Gmail, Microsoft 365 and other providers](https://docs.warmerly.com/help/mailbox-wont-connect) - [What free email deliverability tools does Warmerly have?](https://docs.warmerly.com/help/free-deliverability-tools) ## LinkedIn, WhatsApp & channels - [How do I connect LinkedIn and send LinkedIn outreach?](https://docs.warmerly.com/help/linkedin-outreach) - [What is LinkedIn warmup and how do I turn it on?](https://docs.warmerly.com/help/linkedin-warmup) - [What is Warmerly Link?](https://docs.warmerly.com/help/warmerly-link) - [How do I connect WhatsApp and how many messages can I send?](https://docs.warmerly.com/help/whatsapp-outreach) - [Channel accounts: paid slots and overage](https://docs.warmerly.com/help/channel-slots) - [Which channels can I connect and send from?](https://docs.warmerly.com/help/social-channels) ## Billing & account - [How does Warmerly billing work?](https://docs.warmerly.com/help/how-billing-works) - [What happens when my free trial ends?](https://docs.warmerly.com/help/trial-and-first-charge) - [Why is my workspace locked, or showing Payment failed?](https://docs.warmerly.com/help/billing-locked) - [What happens if I am over my plan's limits?](https://docs.warmerly.com/help/over-plan-limits) - [I ran out of verifications or lookups. Can I buy more without changing plan?](https://docs.warmerly.com/help/buy-more-when-you-run-out) - [What are AI credits, what uses them, and how do I buy more?](https://docs.warmerly.com/help/ai-credits) - [How do client workspaces work, and how do I pay for a second workspace?](https://docs.warmerly.com/help/agency-client-workspaces) - [How do I delete a workspace, and can I get it back?](https://docs.warmerly.com/help/delete-or-restore-workspace) - [How do I invite teammates, and what can each role do?](https://docs.warmerly.com/help/team-members-and-roles) - [What is the audit log and what does it show?](https://docs.warmerly.com/help/audit-log) - [How do I sign in, change my password or email, and secure my account?](https://docs.warmerly.com/help/sign-in-and-security) - [How do I choose which emails Warmerly sends me?](https://docs.warmerly.com/help/email-preferences) - [How does the Warmerly referral programme work?](https://docs.warmerly.com/help/referral-programme) - [How do I apply for and activate Warmerly for Startups?](https://docs.warmerly.com/help/warmerly-for-startups) - [What is Warmerly's refund and cancellation policy?](https://docs.warmerly.com/help/refunds-and-cancellation-policy) - [What happens to my data if I cancel or delete my workspace?](https://docs.warmerly.com/help/data-after-cancelling-or-deleting) - [My account is suspended. What can I do and how do I appeal?](https://docs.warmerly.com/help/account-suspended) - [How do I access, correct or delete my personal data?](https://docs.warmerly.com/help/privacy-requests) ## Apps & support - [How do I use the Warmerly Android app?](https://docs.warmerly.com/help/android-app) - [What can Warmi, the support assistant, do (and how do I reach a human)?](https://docs.warmerly.com/help/warmi-support-assistant) - [How do I connect, check or revoke an AI app (Claude, ChatGPT, Cursor)?](https://docs.warmerly.com/help/manage-connected-ai-apps) - [Is Warmerly down? How the status page and incident banners work](https://docs.warmerly.com/help/status-page) - [Where do I see what's new in Warmerly?](https://docs.warmerly.com/help/whats-new) - [How do I start sending app emails with Warmerly transactional email?](https://docs.warmerly.com/help/transactional-email-getting-started) - [What am I looking at on my Warmerly dashboard?](https://docs.warmerly.com/help/dashboard-overview) --- # How do I use Warmerly with an API? Create an API key in **Settings > Platform API keys**, then send it in an `X-Api-Key` header to `https://app.warmerly.com/api/v1`. API access comes with the **Agency** plan, and the 7-day Agency free trial includes it too, so you can test your integration before paying. Everything the API does is also available in the dashboard. You only need a key when you want your own code, scripts or tools like Zapier to work with Warmerly. ## Which plans include the API? | Plan | API access | | --- | --- | | Free | No | | Starter | No | | Growth | No | | Agency | Yes | | Agency 7-day free trial | Yes | On any other plan, the **Platform API keys** page shows "API access is an Agency plan feature" with an **Upgrade to Agency** button, and API calls answer `403 agency_plan_required`. See [Plans and limits](https://docs.warmerly.com/plans-and-limits) for everything else each plan includes. ## Steps 1. Sign in to [app.warmerly.com](https://app.warmerly.com/login) and open **Settings > Platform API keys**. 2. Under **Create a key**, type a name you will recognise later (for example "Production server" or "Zapier") and click **Create key**. 3. Copy the key straight away. It starts with `wmv_` and is shown only once. If you lose it, revoke it and create a new one. 4. Make your first request. Listing your keys needs nothing but the key itself: ```bash curl https://app.warmerly.com/api/v1/keys \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` A working key returns `{ "keys": [ ... ] }` with the key you just made in the list. 5. Find your project ID. Mailboxes, campaigns and inbox data belong to a project, so most endpoints also need an `X-Project-Id` header. Get the ID from [`GET /workspaces` and `GET /projects`](https://docs.warmerly.com/workspaces), or from the dashboard URL. 6. Call a project endpoint, for example your mailboxes: ```bash curl https://app.warmerly.com/api/v1/accounts \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: YOUR_PROJECT_ID" ``` From there, the [API reference](https://docs.warmerly.com) covers [campaigns](https://docs.warmerly.com/campaigns), [leads](https://docs.warmerly.com/leads), [verification](https://docs.warmerly.com/verify), [inbox](https://docs.warmerly.com/inbox) and [webhooks](https://docs.warmerly.com/webhooks). ## Prefer an AI assistant to writing code? Warmerly also has an MCP server, so ChatGPT, Claude and other assistants can work with your account directly. See [Use with AI (MCP)](https://docs.warmerly.com/ai). ## Common problems **`401 unauthorized`.** The key is wrong, has a typo, or was revoked. Revoked keys stop working immediately. Create a new key and try again. **`403 agency_plan_required`.** The workspace is not on Agency (or an Agency trial). If you just upgraded, allow about a minute for it to take effect. Keys are not deleted when a plan changes, so they work again once the workspace is back on Agency. **`400` "missing X-Project-Id header".** The endpoint is project-scoped. Add the `X-Project-Id` header. [Authentication](https://docs.warmerly.com/authentication) explains which endpoints need it. **`429 too_many_requests`.** Each key has its own per-minute rate limit (60 requests a minute by default). Slow down and retry. Limits for each endpoint are in [Errors and rate limits](https://docs.warmerly.com/errors). ## Related - [Authentication](https://docs.warmerly.com/authentication): headers, scopes and rate limits in detail - [API keys](https://docs.warmerly.com/keys): create, list and revoke keys over the API - [Plans and limits](https://docs.warmerly.com/plans-and-limits): what Agency includes --- # How do I launch my first campaign? Open **Campaigns** in the sidebar and click **New campaign**. A three-step wizard walks you through it: **Audience** (name the campaign and add leads), **Sequence** (write your emails) and **Launch** (choose mailboxes and a schedule, then click **Launch now**). You can do it on the day you sign up. Before you start, connect at least one mailbox under **Accounts**. If you have not done that yet, see [Connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection). ## Steps 1. **Name your campaign.** In **Campaigns > New campaign**, type a **Campaign name** (leads never see it) and click **Create draft**. 2. **Add your audience.** Upload a CSV, search Warmerly's company database, or import from LinkedIn. You can also skip this and add leads later from the campaign's **Audience** tab. CSV steps are in [How do I import leads from a CSV?](https://docs.warmerly.com/help/import-leads-csv) 3. Click **Next: write your sequence**. 4. **Write your sequence.** Pick a template or start from scratch. Use **Insert variable** to add merge tags like `{{firstName}}` or `{{companyName}}`. Your edits save automatically, so there is no Save button. 5. Click **Next: choose senders and launch**. 6. **Choose senders.** Under **Email accounts**, every healthy mailbox is ticked for you. Emails are spread evenly across the ones you pick. 7. **Set the schedule.** Choose the **Sending days**, **Start hour**, **End hour**, **Timezone** and **Daily limit**. The default is Monday to Friday, 9:00 to 17:00. 8. **Check "Ready to launch?"** Each item that needs attention has a **Fix this** or **Fix in Settings** link. Warnings can be accepted; blockers (no sender, no leads, an empty step, a merge tag that does not exist) must be fixed first. 9. Click **Launch now**. You will see "Campaign started". Prefer to wait? Click **Save as draft** and use **Start** on the campaign page later. ## What happens after launch - Nothing is sent outside your sending days and hours. - **New mailboxes start slowly.** If a mailbox has had less than 14 days of warmup, the campaign ramps its volume: 3 emails per mailbox on the first sending day, climbing each sending day after that. This protects your reputation, so launching early is safe. - Keep warmup switched on. It keeps running alongside your campaigns. - Use **Pause** and **Resume** at the top of the campaign page at any time. The **Settings** tab holds the schedule, stop-on-reply and tracking options. ## Plan limits to know Your plan sets how many campaigns can be active at once, how many leads you can hold and how many campaign sends you get a month. The numbers for every plan are in [Plans and limits](https://docs.warmerly.com/plans-and-limits). The free mailbox every account gets is for warmup, replies and tests, not campaigns. To send, connect your own mailbox or add a OneMail mailbox. See [How do I get a free sending mailbox?](https://docs.warmerly.com/help/free-sending-mailbox) ## Common problems **"Launch now" is greyed out or a check is failing.** Read the "Ready to launch?" list. The usual blockers are no leads added, no mailbox selected, or a merge tag in your emails that is not in your lead data. **Launching is refused because of your active campaign limit.** Paused campaigns count towards it too. Archive one you no longer need, or upgrade. Drafts never count. **The campaign is live but nothing went out.** Check the sending window and timezone first, then work through [A campaign is not sending](https://docs.warmerly.com/troubleshooting#a-campaign-is-not-sending). ## Related - [How warmup works](https://docs.warmerly.com/how-warmup-works) - [Troubleshooting](https://docs.warmerly.com/troubleshooting) - [Campaigns API](https://docs.warmerly.com/campaigns) --- # How do I import leads from a CSV? Leads are imported straight into a campaign. Open the campaign, go to its **Audience** tab and click **Import leads** (or use the upload box in step one of the **New campaign** wizard). Drop in your CSV file, point one column at **Email**, match any other columns you want, and click **Import**. Your column names can be anything. ## Steps 1. Export your list as a **CSV** file. From Excel or Google Sheets, choose **File > Download > CSV** (or **Save As > CSV**). `.csv`, `.tsv` and `.txt` files work. Excel files (`.xlsx`, `.xls`) do not, so convert them first. 2. In Warmerly, open **Campaigns**, pick the campaign and go to the **Audience** tab. Click **Import leads**. For a new campaign, the same importer is in the first step of the wizard after you click **Create draft**. 3. Drag your file onto the box, or click **Choose a file**. You can also click **Paste instead** and paste rows copied from a spreadsheet. 4. **Match the columns.** Warmerly guesses the obvious ones (like "Email Address" or "Company Name"). For each column choose one of: **Email (required)**, **First name**, **Last name**, **Company**, **Website**, **Import as custom field** or **Don't import**. 5. Check the live count above the table: rows, valid emails, duplicates and skipped rows. 6. Click **Import**. The button shows how many leads will be added. 7. Read the result: how many leads were added, how many were already in the campaign, and how many were rejected as undeliverable. ## Use your columns in emails Every column you import as a **custom field** becomes a merge tag. A column called "Job Title" becomes `{{Job_Title}}`, and you can rename the tag before importing. The standard fields become `{{firstName}}`, `{{lastName}}`, `{{companyName}}` and `{{email}}`. Add them to your emails with **Insert variable** in the sequence editor. A **Website** column is also used to research each lead when you write with the `{{ai_opener}}` tag. ## What gets cleaned up for you - Rows with a missing or broken email address are skipped. - Duplicate addresses in the file are removed (the first one is kept). - Leads already in the campaign are not added twice. - Each address gets a free quick check on import. Addresses with no mail server or from disposable providers are dropped, because they would bounce. This does not use your verification allowance. - Unsubscribed and bounced addresses can be imported, but they are never sent to. Warmerly checks the [suppression list](https://docs.warmerly.com/suppression) right before every email. For a deeper check (like mailbox-level verification), run the list through **Email verification** first. See the [Verify API](https://docs.warmerly.com/verify). ## How many leads can I import? Each campaign has a lead limit that depends on your plan: 500 on Free, 2,500 on Starter, 25,000 on Growth and 100,000 on Agency. Importing from your own CSV never uses your lead export allowance. See [Plans and limits](https://docs.warmerly.com/plans-and-limits). ## Common problems **"... is a spreadsheet, not a CSV".** You uploaded an Excel or Numbers file. Download it as CSV and try again. **The Import button stays greyed out.** No column is set to **Email**. Pick the column that holds the addresses and choose **Email (required)**. **"This campaign holds ... leads, so ... more will not fit".** The list is bigger than your plan's per-campaign limit. Split it across two campaigns, or upgrade. **Merge tags send as blank text.** The tag in your email does not match a column name. The sequence editor warns you about tags that do not exist, so check the spelling. ## Related - [How do I launch my first campaign?](https://docs.warmerly.com/help/launch-first-campaign) - [Leads API](https://docs.warmerly.com/leads) and [Campaigns API](https://docs.warmerly.com/campaigns) for importing from code - [Suppression](https://docs.warmerly.com/suppression) --- # Why did my mailbox disconnect, and how do I reconnect it? A mailbox shows **Disconnected** when Warmerly can no longer sign in to it. The usual reasons are a changed password, a deleted or revoked app password, or a Microsoft sign-in that was revoked or expired. To fix it, open the mailbox from **Accounts** and click **Reconnect**. Nothing is lost while it is disconnected. ## What a disconnected mailbox means - On **Accounts**, the mailbox shows a **Disconnected** status and a red **Reconnect** badge. - Warmup and campaign sending from that mailbox stop until you reconnect it. Your campaigns themselves are not paused, and other mailboxes keep sending. - Warmerly usually raises an alert titled "Reconnect needed" and includes it in your alert email (unless you have turned alert emails off). Warmerly only marks a mailbox disconnected after repeated failures (for example three refused logins in a row), so one blip does not trigger it. If the mail server was only unreachable, Warmerly keeps retrying on its own every 30 minutes. A wrong password is never retried, because it will not fix itself. ## Steps to reconnect 1. Go to **Accounts** and click the mailbox. 2. Click **Reconnect** at the top of the mailbox page. 3. What happens next depends on how the mailbox was connected: - **One-click sign-in (Microsoft 365, Outlook.com, Hotmail):** you are sent back to Microsoft's sign-in screen. Sign in with the same address and accept every permission. - **App password or SMTP/IMAP:** Warmerly first tries your saved details again. If they still work, you will see "That mailbox signs in fine" and you are done. If not, a **Reconnect** window shows the mail server's reason and asks for the **Mailbox password**. You can also open **Change server settings** to fix a host or port. - **OneMail and the free mailbox:** Warmerly issues a new mail password itself. You are never asked for one. 4. Click **Reconnect** in the window. Warmerly signs in to both SMTP (sending) and IMAP (reading) before saving anything, so if it works here, it works for real. After a successful reconnect, warmup is scheduled again straight away and carries on from where it stopped. It does not start over. ## Why it happened, and how to stop it happening again | What you see | What it means | What to do | | --- | --- | --- | | "Wrong username or password" | The password changed, or the app password was deleted | For Gmail and Google Workspace, create a new [app password](https://docs.warmerly.com/guides/mailbox-connection#gmail-and-google-workspace-app-password) and enter it | | "needs an app password, not the password you sign in with" | The account has two-step sign-in | Use an app password, not your normal password | | "The provider blocked this sign-in as unusual" | Google or Yahoo wants you to confirm it was you | Sign in to webmail in a browser, confirm, then reconnect | | "Microsoft has SMTP sending switched off" (5.7.139) | Authenticated SMTP is off for your Microsoft 365 organisation | An admin turns it on. See [Microsoft 365 troubleshooting](https://docs.warmerly.com/troubleshooting#microsoft-365-smtp-username-or-password-failed-but-oauth-reconnected-fine) | | "Couldn't reach the mail server" | The host or port is wrong, or the server is down | Check the settings under **Change server settings** | | "The provider is temporarily blocking logins" | Too many login attempts | Wait a few minutes, then try again | Changing your email password, or deleting the app password in your Google account, will disconnect the mailbox. Reconnect it right after any password change. ## Common problems **Microsoft says the sign-in worked, but sending still fails.** This is almost never the password. See [Microsoft 365: authentication unsuccessful](https://docs.warmerly.com/guides/mailbox-connection#microsoft-365-authentication-unsuccessful-after-a-successful-reconnect). **"Resume" does not bring it back.** Resume checks the login first and refuses while the password is wrong. Use **Reconnect** instead. **Google says app passwords are "not available for your account".** 2-Step Verification is off, or your Workspace admin has not allowed it. [Here is the fix](https://docs.warmerly.com/guides/mailbox-connection#google-workspace-the-setting-you-are-looking-for-is-not-available-for-your-account). ## Related - [Connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection) - [Troubleshooting](https://docs.warmerly.com/troubleshooting) - [Webhooks](https://docs.warmerly.com/webhooks) to get mailbox health events in your own tools --- # How do I cancel or change my plan? Everything is in **Settings > Billing**. To move to another paid plan, click **Switch to this plan** on the plan you want; the change takes effect immediately. To cancel, click **Manage billing**, which opens Stripe's secure billing portal, and cancel there. Nothing in your account is deleted when you cancel or downgrade. Plan changes are always yours to make. Support and Warmi can explain your options but cannot change or cancel a plan for you. ## Change your plan 1. Open **Settings > Billing** in [app.warmerly.com](https://app.warmerly.com/login). 2. Under **Choose your plan**, find the plan you want. **Compare all tiers** shows every limit side by side. 3. Click **Switch to this plan**. Upgrades and downgrades between Starter, Growth and Agency work the same way. Prices are on [warmerly.com/pricing](https://warmerly.com/pricing) and allowances are in [Plans and limits](https://docs.warmerly.com/plans-and-limits). 4. You will see "Plan updated. Changes take effect immediately." On the Free plan with no subscription yet, the button reads **Start 7-day trial** instead. A card is needed, and nothing is charged until day 8. Want to pay yearly? If you already pay monthly, the **Switch to annual** card on **Settings > Billing** moves you to annual billing on your current plan, and shows what you would save. It is not shown once you are already on annual. Annual prices are on [warmerly.com/pricing](https://warmerly.com/pricing). To pay in GBP, start from the pricing page. ## Cancel your subscription 1. Open **Settings > Billing**. 2. Click **Manage billing**. Stripe's billing portal opens. 3. Choose to cancel your subscription and confirm. **On a paid plan**, you keep everything you paid for until the end of the current billing period. After that, the workspace moves to the **Free** plan. It is not closed, and your mailboxes, campaigns, leads and inbox are all kept. **During a free trial**, cancelling ends the trial straight away rather than at its end date, and you are not charged. Warmerly stops sending, but nothing is deleted, so you can pick a plan again whenever you want. The same **Manage billing** portal is where you update your card and download invoices. ## What happens if I am over the new plan's limits? - **Downgrading to a smaller paid plan:** you get a grace period, shown as a countdown banner, to come back inside the new limits. Everything keeps running during it. - **Moving to Free** (after cancelling): Free allows 1 mailbox and 1 active campaign. If you have more, campaign sending and warmup pause straight away until you are back inside Free's limits or pick a paid plan again. Nothing is removed. To get back inside a limit, disconnect mailboxes you no longer use or pause and archive campaigns. The full rules are in [Plans and limits](https://docs.warmerly.com/plans-and-limits#what-happens-when-you-hit-a-limit). ## Common problems **"Cancel from the billing portal to move to Free".** You cannot pick Free directly while a paid subscription is running. Cancel it in **Manage billing**; the workspace moves to Free when the paid period ends. **Sending stopped after I cancelled.** You are probably over Free's limits. Remove extra mailboxes or pause campaigns, or choose a paid plan again. ## Related - [Plans and limits](https://docs.warmerly.com/plans-and-limits) - [FAQ: plans and billing](https://docs.warmerly.com/faq#plans-and-billing) --- # How do I get a free sending mailbox? You already have one. Every new Warmerly account gets a free mailbox, created for you at signup and already warming up. You will find it under **Accounts** with a **Free gift** badge. It costs nothing, does not use a mailbox slot on your plan, and needs no domain or DNS setup, because it lives on a domain Warmerly owns. ## What the free mailbox can do - **Warmup: always on.** It started by itself at signup, and you cannot switch it off. - **Replies and tests.** Use it to try Warmerly out, send yourself a test, and reply to mail that arrives in it. - **Not for cold campaigns.** It lives on a shared domain, so it does not send campaigns. To send campaigns, connect your own mailbox or add a hosted OneMail mailbox (see below). - **One per person.** Each user gets one free mailbox, ever. ## Steps to use it 1. Verify your email address, if you have not already. 2. Open **Accounts** and click the mailbox with the **Free gift** badge. The panel "This one's on us" shows what it can and cannot do. 3. To run a campaign, connect your own mailbox (Google, Microsoft or SMTP) or add a OneMail mailbox, then create one from **Campaigns > New campaign**. See [How do I launch my first campaign?](https://docs.warmerly.com/help/launch-first-campaign) ## How long can I keep it? As long as you are using Warmerly. It is only closed after **60 days with no activity** from you, and you get two reminder emails first with a **Keep my mailbox** button. Signing in resets the clock. Once you connect your own mailbox or buy a OneMail mailbox, there is no countdown at all. ## Need more volume? Get a hosted OneMail mailbox To send campaigns, connect your own mailbox ([Connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection)) or let Warmerly host one for you with **OneMail**. A hosted mailbox sends to verified addresses: 1. Go to **Accounts** and click **Add**. 2. Choose **OneMail mailbox (we host it)**. Warmerly sets up the domain and DNS for you. 3. Pick a route: **Get a ready-warmed mailbox** (already has 21+ days of warmup, when available), **Add mailboxes to a domain you already have**, **Buy a new domain**, or **Connect a domain I own**. OneMail is billed per mailbox per month, and the price drops on bigger plans: | Your plan | Price per OneMail mailbox | | --- | --- | | Free or Starter | $2.99/mo | | Growth | $1.99/mo | | Agency | $0.99/mo | OneMail mailboxes never use your plan's mailbox limit. Ready-warmed mailboxes cost the same as any other OneMail mailbox. You can buy OneMail on the Free plan too; a card is needed. ## Common problems **My campaign will not send from the free mailbox.** That is expected. The free mailbox does not run campaigns, and neither you nor support can switch that on. Connect your own mailbox or add a OneMail mailbox. **Can I pause warmup on it?** No. Warmup is always on for the free mailbox. **Do I need a password for it?** No. You are never asked for credentials. If it ever shows **Reconnect**, clicking it makes Warmerly issue a new mail password itself. ## Related - [How warmup works](https://docs.warmerly.com/how-warmup-works) - [Plans and limits](https://docs.warmerly.com/plans-and-limits) - [Why did my mailbox disconnect?](https://docs.warmerly.com/help/reconnect-mailbox) --- # OneMail: mailboxes and domains hosted by Warmerly OneMail is the way to get sending mailboxes without touching Google Workspace or Microsoft 365. Warmerly hosts the mailbox on its own mail servers, sets up the domain's DNS, starts warmup and connects it to your campaigns and inbox. It is not Google Workspace or Microsoft 365: the mailboxes are ordinary IMAP and SMTP mailboxes on Warmerly's own infrastructure. Everything below is done while signed in, under **Accounts** > **Add** > **OneMail mailbox (we host it)**. There is no separate OneMail page. ## Four ways in 1. **Buy a new domain.** Search a name in the wizard. It shows whether the name is available and the yearly registration price live from the registrar before anything is charged. You never have to touch DNS. 2. **Connect a domain I own** (Namecheap, GoDaddy, Cloudflare or anywhere else). By default you change the domain's nameservers at your registrar to the two the wizard shows, which takes about two minutes plus propagation, and Warmerly then manages the records. If you would rather keep your current DNS provider, choose "Add records manually instead" and add the records yourself (see below). There is no domain fee. You do not need to buy a domain from Warmerly. 3. **Add mailboxes to a domain you already have.** Shown once you have a OneMail domain. No DNS to touch. Warmup starts the same day. 4. **Get a ready-warmed mailbox.** Sometimes there are mailboxes that have already finished warmup. The option appears in the wizard only when some are in stock, and they can send campaigns the same day. You can use several domains, and several mailboxes on each. Two domains with two mailboxes each is fine. ## How much is a domain if I buy it through Warmerly, and where do I buy one? You buy it inside the app, after you sign in: **Accounts** > **Add** > **OneMail mailbox (we host it)** > **Buy a new domain**. Type a name and the wizard shows whether it is available and its price straight from the registrar, both the first-year registration price and the yearly renewal. The price depends on the ending (.com, .co and so on), so there is no single figure to quote here. You see it before anything is charged. The Buy a domain option is only visible once you have an account, so a visitor browsing the website will not see it yet. Warmi can also look up the live price of a specific name for you. ## What Warmerly sets up for you For a domain you buy, or a domain you connect by nameservers, Warmerly publishes the MX, SPF, DKIM and DMARC records itself. On a connected domain that is done as soon as the nameserver change reaches the internet. The domain's page under **Accounts** shows each step and a **Check now** button while it waits. ### If you add the records yourself On the manual route Warmerly does not publish anything. The wizard lists the records to add at your DNS provider: MX, SPF, DKIM and DMARC records for the domain, plus a bounce MX and SPF record, and, when offered, an optional tracking CNAME. Add every required one, because skipping one hurts deliverability. Warmerly checks for them about every minute and carries on by itself once they resolve. Only your DNS provider decides how long that takes. If the domain already receives email, both DNS routes stop before changing any MX record and recommend a secondary sending domain instead, so your existing inboxes keep working. ## Warmup and sending volume Warmup starts automatically and stays on. A new mailbox starts campaigns on a volume ramp, from a few emails a day, climbing as it warms. It is fully warm after about two weeks, longer on a brand new domain. A new mailbox's daily limit defaults to 30 campaign emails a day, and the ramp keeps the first days below that. Do not raise it early. See [How warmup works](https://docs.warmerly.com/how-warmup-works). ## Sending and receiving A OneMail mailbox sends and receives normal mail. Replies to your campaigns arrive in the Warmerly **Inbox**, alongside every other mailbox, and stop that prospect's remaining follow-ups. ## Cold email Outreach to businesses is what Warmerly is for, and OneMail mailboxes can be used for it. You must follow the [Acceptable Use Policy](https://warmerly.com/acceptable-use): lawful outreach to business contacts, with no bought or rented lists and no consumers without the consent their country's law requires. Accounts that break it can be suspended. ## What it costs OneMail is billed per mailbox, monthly, on your existing subscription. The per-mailbox rate is lower on higher plans, and there is no minimum. A OneMail mailbox never uses up the mailbox limit of your plan. A Free workspace can also buy them by adding a card. Domain registration is a separate, one-off yearly fee shown in the wizard before you pay, and it is not charged when you connect a domain you already own. Current prices are on [the pricing page](https://warmerly.com/pricing). ## If a mailbox has deliverability problems Warmerly watches every mailbox and pauses sending when reputation drops, and the mailbox's page shows the DNS and blocklist checks with the fix. Replacing a mailbox is not an automatic promise: tell support at support@warmerly.com with the mailbox address and it will be looked at. --- # Frequently asked questions ## Warmup **Does warmup send email to my prospects?** No. Warmup traffic goes only between mailboxes inside Warmerly's private warmup network, in both directions. Your lists are untouched until a campaign sends. [How warmup works](https://docs.warmerly.com/how-warmup-works) **How long should I warm a mailbox before sending?** You don't have to wait: a campaign on young mailboxes (under 14 days of warmup) starts slowly by itself (3 emails per mailbox on day one, climbing) so you can launch today. A mailbox is fully warm after about two weeks, longer on a brand-new domain. Keep warmup on afterwards; it is maintenance, not a one-off setup step. **Can I skip warmup if my mailbox is old and already in use?** You can, but an established mailbox has reputation for its *existing* sending pattern. Outbound campaigns are a new pattern, and ramping into them is what stops providers treating the change as suspicious. **My warmup reply rate is 60% but my campaign replies are near zero. Why?** Those are two unrelated metrics with similar names. The warmup figure measures activity inside the warmup network; the campaign figure measures real people. [The difference](https://docs.warmerly.com/how-warmup-works) **Does it matter who hosts my mailbox?** No. The warmup network spans many providers, so Gmail, Outlook and others see the activity regardless of where your sending address is hosted. **Is warmup included in my plan?** Yes, on every plan including Free, and it is never metered. What limits warmup is how many mailboxes your plan lets you connect. ## Plans and billing **Is Free a trial?** No - no card, no expiry, stay as long as you like. Paid tiers separately include a 7-day free trial, which does need a card and charges nothing until day 8. **Do you have a startup program? (Warmerly for Startups)** Yes. Companies founded in the last 3 years that have raised under $5M in total, and are not lead-generation agencies or resellers, can apply at [warmerly.com/startups](https://warmerly.com/startups). Approved startups get Agency free for 3 months (a 90-day trial), then $89.50/month (50% off) for 9 months, then the normal $179/month, plus a priority setup call. (A test keeps these numbers in step with the Agency plan.) A person reviews every application; the approval email links to **Settings > Billing** to activate it. A card is needed to activate, like any trial, and there is no code to enter. **What is the 30-day free trial offer?** Visitors who claim it on warmerly.com get 30 days free on any paid plan instead of 7. A card is needed at checkout and the first charge is on day 31. It must be used within 14 days of creating the account, once per account, and the billing page always shows the trial length that applies to you. **Is sending metered?** Not on paid plans. See [plans and limits](https://docs.warmerly.com/plans-and-limits) for what actually bounds your volume. **What does LinkedIn cost?** It is billed per connected account each month, separate from your plan, with no trial. The current price is on [warmerly.com/pricing](https://warmerly.com/pricing). **What happens when I hit a limit?** The action is refused with an explanation, and nothing is deleted. Going over your plan overall gives you a grace period, then sending and warmup pause until you are back inside it or upgraded. [Details](https://docs.warmerly.com/plans-and-limits) **Do unused monthly allowances roll over?** No. Verifications, lookups, exports, placement tests and AI credits reset on the 1st. **Am I charged for a lookup that finds nothing?** No. An allowance is only debited when the action actually returned a result. **How do I cancel, change my card, or get an invoice?** **Settings > Billing > Manage billing** opens the Stripe portal, which owns all three. **Can support change my plan for me?** No - plan changes are always yours to make, with your own card, at **Settings > Billing**. Warmi can read your plan and usage but has no ability to change either. ## Mailboxes and deliverability **How many mailboxes do I need?** Work back from volume: mailboxes x daily limit (30/day by default). For 300 sends a day you want about ten warm mailboxes, not one mailbox pushed ten times as hard. **Do I have to set up DKIM, SPF and DMARC?** Yes, for anything you intend to send at scale. They are the difference between delivered and spam before your copy even gets read. [Guides](https://docs.warmerly.com/guides) **Warmerly says my DKIM is missing but it is configured.** That is almost always a custom selector Warmerly could not guess. [Fix](https://docs.warmerly.com/troubleshooting) **My Microsoft 365 mailbox reconnected but sending fails with a password error.** Usually a mailbox-identity mismatch or tenant-disabled SMTP AUTH, not a wrong password. [Fix](https://docs.warmerly.com/troubleshooting) **Can I use a shared or alias mailbox?** Yes, with the SMTP/IMAP username set to that mailbox's own address, provided the signed-in account has Send As or Full Access rights. **What is a placement test?** A live probe that sends real email from your mailbox to seed addresses across providers and reports inbox vs promotions vs spam. Each run spends one of your monthly placement tests. [More](https://docs.warmerly.com/troubleshooting) ## Campaigns, leads and inbox **My campaign is not sending.** There is an ordered checklist for this - status, mailboxes, daily limits, schedule, billing state, suppression. [Work through it](https://docs.warmerly.com/troubleshooting) **Can two campaigns share a mailbox?** Yes, and they share that mailbox's daily limit rather than each getting a full one. **What does "active prospects" mean?** Unique people across your active and paused campaigns, counted workspace-wide - distinct from the per-campaign lead ceiling. **Can I bring my own leads?** Yes, by import, and Warmerly also has its own company and contact database you can search and pull from, metered as lead exports. [Leads API](https://docs.warmerly.com/leads) **Does Warmerly verify addresses before sending?** Verification is its own tool with its own monthly allowance, and it is worth running on imported lists - bouncing a bad list is one of the fastest ways to damage a mailbox you spent weeks warming. [Verify API](https://docs.warmerly.com/verify) **Are replies separated from warmup traffic?** Yes. Warmup mail is kept out of your inbox view and never graded. Replies from people who are leads in your campaigns are sorted into Interested, Not relevant and Spam; other mail stays Unclassified and shows only under **All**. [How the Inbox works](https://docs.warmerly.com/help/inbox) · [Inbox API](https://docs.warmerly.com/inbox) **How do I make sure someone is never contacted again?** Add them to the suppression list; suppressed addresses are never sent to by any campaign. [Suppression](https://docs.warmerly.com/suppression) ## API and integrations **Which plan has API access?** Agency. [Authentication](https://docs.warmerly.com/authentication) **How do I authenticate?** An `X-Api-Key` header, plus `X-Project-Id` to say which project you are acting in. [Authentication](https://docs.warmerly.com/authentication) **Are there rate limits?** Yes, per endpoint group, and they are separate from your plan's monthly allowances. [Errors and rate limits](https://docs.warmerly.com/errors) **Can I get notified instead of polling?** Yes - subscribe to outbound webhooks for mailbox health events. [Webhooks](https://docs.warmerly.com/webhooks) ## The app itself **Is there a mobile app?** Yes, an Android app covering accounts, campaigns, leads and Warmi support chat. It also has an inbox with your replies, and sends a push notification when a genuine reply arrives (warmup traffic never notifies). [Android app guide](https://docs.warmerly.com/help/android-app) · [warmerly.com/android](https://warmerly.com/android) **Who is Warmi?** The assistant in the chat widget. Warmi searches these docs in front of you, can read your own mailbox, campaign, plan and usage data when you are signed in, and can hand a conversation to a human. Warmi cannot change your billing or your plan - by design, there is no tool for it. **Can I manage several clients in one account?** Yes. Projects separate clients or brands inside a workspace, each with their own mailboxes, campaigns and inbox. [Workspaces and projects](https://docs.warmerly.com/workspaces) --- # How warmup works Warmup is the part of Warmerly that builds a mailbox's sending reputation **before** you use it for real outreach. It is a separate system from campaigns, and the single most common misunderstanding about it is worth stating first. ## Warmup never emails your prospects A mailbox in warmup does not send cold email to anyone on your lists. It exchanges ordinary-looking email with other mailboxes inside Warmerly's private warmup network: - your mailbox sends warmup messages to network peers, - peers send warmup messages **back** to your mailbox, - both sides open and reply to a tuned share of what they receive. That two-way traffic is what mailbox providers read as "this address is used by a real person who gets real replies." It is invisible to your prospects, and it is the reason warmup works at all, one-directional sending into a void builds nothing. Real outbound to real leads happens only through [Campaigns](https://docs.warmerly.com/campaigns). The order that works is: connect the mailbox, authenticate the domain, warm it up, then point campaigns at it. ## The ramp Warmup starts small and increases the mailbox's daily volume over time rather than sending its full allowance on day one. A brand-new address that suddenly sends dozens of messages looks exactly like a compromised or purchased one, so the ramp is doing reputation work even on the days it looks slow. Two numbers bound a mailbox's volume: | Setting | What it does | | --- | --- | | Daily sending limit | The mailbox's own ceiling for campaign sends per day. New mailboxes default to **30/day**. | | Ramp | While a mailbox is still ramping, the effective daily figure is lower than that ceiling and climbs toward it. | You can raise a mailbox's daily limit on the mailbox's own settings, but raising it does not skip the ramp, deliverability is earned over days, not set in a field. **How long should warmup run before I send?** You don't have to wait to launch. A campaign whose mailboxes have had less than 14 days of warmup starts with a **volume ramp** by default: 3 emails per mailbox on day one, climbing as the mailbox warms, so launching the day you connect is safe. A mailbox is fully warm after about two weeks, longer on a brand-new domain. Keep warmup enabled after campaigns start: it is not a setup step you finish, it is the background activity that keeps the mailbox healthy. ## Reputation is cross-provider Your mailbox can be hosted anywhere: Google Workspace, Microsoft 365, Zoho, IONOS, your own server. The warmup network itself is spread across many providers, so the activity your mailbox takes part in is seen by Gmail, Outlook and the rest regardless of who hosts the sending address. Where your mailbox is hosted does not limit which providers learn to trust it. ## Two different "reply rates" These look like the same metric and are not. Mixing them up is the second most common warmup question we get. | Where you see it | What it measures | | --- | --- | | **Warmup reply rate (7d)** / **Warmup open rate (7d)** on a mailbox's page | Activity *inside the warmup network only*, how often peer mailboxes opened or replied to warmup mail. Internal, tuned, and says nothing about your prospects. | | **Reply rate** on a campaign's page | Real leads replying to your real outbound. This is the number that reflects your outreach. | So a 60% "warmup reply rate" is not a prediction of campaign performance, and a quiet campaign reply rate is not a warmup fault. ## Checking it is working Run a [placement test](https://docs.warmerly.com/help/placement-tests) from the **Inbox placement** card on the mailbox's **Health** tab (**Run new test**). It sends probe emails through that mailbox to seed addresses across providers and reports where each one landed, inbox, promotions or spam. That is the direct answer to "is this mailbox healthy," and it is worth more than any single rate on a dashboard. ## LinkedIn warmup is a different mechanism LinkedIn warmup is not email warmup pointed at another channel. There is no peer network: Warmerly automates real activity on your own connected LinkedIn account, posts, reactions, comments, profile views and connection invitations, generated from the topics, industries and guidelines you configure under **Accounts → your LinkedIn account → LinkedIn warmup settings**. It requires a paid LinkedIn slot (LinkedIn is sold per account, separately from the base plans, see [Plans and limits](https://docs.warmerly.com/plans-and-limits)). ## Warmup and your plan Warmup is included on every plan, Free included, and warmup traffic is never metered against a sending allowance. What bounds warmup is how many mailboxes your plan lets you connect. One exception worth knowing: while a workspace is locked out for billing, **warmup stops along with campaign sending** until the lock clears. Campaigns are not reset, and both resume by themselves within a few minutes of the workspace getting back inside its plan. ## See also - [Warmup API](https://docs.warmerly.com/warmup): warmup health, stats and trends over HTTP - [Setting up DKIM](https://docs.warmerly.com/guides/dkim) and [SPF & DMARC](https://docs.warmerly.com/guides/spf-dmarc). Do these before warmup, not after - [Troubleshooting](https://docs.warmerly.com/troubleshooting): paused mailboxes, placement problems, DKIM false alarms --- # How our email infrastructure works This page explains how Warmerly sends mail for the mailboxes we host, and how it keeps one sender's problems away from everyone else. It describes the model, not the machinery: server names and addresses are left out on purpose, because publishing them would help spammers and attackers more than it would help you. Three words used below: - **Sending address**: the internet address (IP address) a mail server sends from. Receiving providers keep a reputation for each one. - **Sending domain**: the part of your email address after the @. Providers keep a reputation for that too. - **Receiving provider**: whoever runs the inbox a message is going to, for example Gmail, Microsoft (Outlook and Microsoft 365), Yahoo or Apple (iCloud). > **Which mailboxes this is about.** Mailboxes Warmerly hosts for you (OneMail), ready-warmed > mailboxes you buy from us, and the free mailbox new accounts get. A mailbox you connected from > your own provider, such as Gmail or Microsoft 365, sends through that provider, so it uses that > provider's sending addresses, not ours. The bounce brake and the automatic pauses for high > bounces and spam refusals in [Why did my sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused) > still apply to it. ## How mail reaches a hosted mailbox, and how it leaves Mailboxes Warmerly hosts (OneMail) sit on mail servers we run. A domain lives on one of them, and the servers work as a pool, so we can add capacity or move a domain without you doing anything. **Mail coming in.** When someone emails `you@yourdomain.com`, their provider looks up your domain's **MX record**. It names our mail server for your domain; the message is delivered there, stored in the mailbox, and shown in your Warmerly inbox. Hosted mailboxes are ordinary IMAP and SMTP mailboxes, so they can also be used from a mail app. **Mail going out.** A message sent from your mailbox goes through our sending network, which sends it from the paid lane's sending addresses (see below). The receiving provider then checks three things against your domain's DNS before it decides where the message goes: - **SPF**: is this sending address allowed to send for your domain? - **DKIM**: is the signature on the message valid? We sign every message with your domain's own key. - **DMARC**: do SPF and DKIM line up with the address in the From line? Hosted mailboxes are set up so they do. Bounces (replies that say "this address does not exist") are routed to a `bounce` address on your own domain, so they come back to us rather than to your inbox. ## What DNS records do I add for a Warmerly-hosted mailbox? Warmerly shows you the exact records on the domain page, and that page is the one to copy from. The records below describe what each one is for. Every record points at Warmerly’s stable names: `mail.warmerlymail.com` for incoming mail and `_spf.warmerlymail.com` for sending. `mail.warmerlymail.com` is one front door for every customer: it looks up which of our mail servers holds your mailbox and hands your mail to it, so a server move is a change in our system and not in your DNS. A domain set up earlier may show a different server name instead, and keeps working. Publish them at the company that runs your domain's DNS (a registrar such as GoDaddy or Namecheap). If we manage your DNS for you (an automatic setup), we publish them and there is nothing to do. | Record | Name | Value | What it does | | --- | --- | --- | --- | | MX | your domain (`@`) | `mail.warmerlymail.com` (also shown on your domain page), with the priority shown there | Sends incoming mail to our mail server | | TXT (SPF) | your domain (`@`) | `v=spf1 include:` followed by the value shown on your domain page, then `-all` | Allows our sending addresses to send as your domain | | TXT (DKIM) | the selector shown on the page, then `._domainkey` | the key shown on the page | Lets receivers verify your messages' signature | | TXT (DMARC) | `_dmarc` | `v=DMARC1; p=none` at first | Tells receivers what to do when a check fails | | MX | `bounce` | the same mail server name, with the same priority | Receives bounces for your domain | | TXT (SPF) | `bounce` | the same SPF value as above | Allows bounce handling to work | A few rules that avoid the common problems: - **Only one MX target on the main domain.** A leftover MX record from a previous provider at an equal or better priority splits your incoming mail between two servers. The domain page flags it. - **Only one SPF record.** If your domain already has an SPF record (for example one from Google Workspace), add our `include:` into it rather than adding a second record. Two SPF records are an error and every message fails SPF. - **Leave the DKIM record exactly as shown.** Some DNS providers wrap or trim long values; if the key does not match, the domain page shows the record as missing. - **Records can take time to appear.** Up to an hour is normal, occasionally longer. We re-check automatically and the mailbox switches on by itself once everything is live. The step-by-step version for each DNS provider is in the [DNS and mailbox setup guides](https://docs.warmerly.com/guides/dns-records), and the app's domain page shows which records are live and which are still missing. ## Do I need to change my DNS if Warmerly moves servers? Mostly not. The mail server names (`mail.warmerlymail.com`) and `_spf.warmerlymail.com` belong to Warmerly, and we point them at whichever server your mailbox is on. When we move a mailbox to another server, or change the sending addresses behind it, the MX and SPF records you published stay exactly as they are. **The one record that can change is DKIM.** Each server signs with its own private key, and keys never leave the server that made them, so a moved mailbox gets a new DKIM key. - **If we manage your DNS** (an automatic setup), we publish the new key ourselves. You do nothing. - **If you manage your own DNS**, we email you the new DKIM record first. We build and test your mailbox on the new server, and we only switch over once the new record is live, so nothing breaks while you add it. Until then your mailbox stays where it is, on the old record. If you set a mailbox up earlier, your MX and SPF records may name one of our servers directly instead of the names above (for example a name beginning `mx` followed by a number). Those keep working and keep verifying as correct, so you do not have to change them. ## How we keep our own domains from hurting your mail Spam blocklists score the domains a message shows: the From address, the signing domain, the bounce address, the server's name and the links inside it. Warmerly keeps its own infrastructure domain out of every one of those places. - **The domain in your DNS records is never in your messages.** `warmerlymail.com` is used only for the names above. It is not in the From line, the DKIM signature, the bounce address, the server's name or any link. - **Links never carry our domains.** Customers cannot use Warmerly's own domains as a link domain, and when there is no safe link domain, campaign mail carries no link of ours at all. - **Our own domains are checked regularly** against the major blocklists, and our team is emailed the moment one is listed. While one of our sending addresses is listed, campaign mail from the hosted mailboxes behind it is held automatically, and resumes by itself once it clears. - **Servers identify themselves with the hosting provider's name, never a Warmerly domain.** A blocklisted company domain is the one thing that can stop us getting a sending address delisted. ## Paid, ready-warmed and free mailboxes are kept apart Warmerly hosts three kinds of mailbox, and each kind sends in its own lane: | Lane | What it is | How it is kept apart | | --- | --- | --- | | **Paid** | Hosted mailboxes (OneMail) that customers order, on their own domains or on domains bought through us | Customers' own domains | | **Ready-warmed** | Mailboxes that have already finished warmup, so a customer can buy one and send the same day | Domains we own and use only for this, not the free mailboxes' domains. Once bought, the mailbox moves to the buyer's workspace with its history | | **Free** | The free mailbox new accounts get, on shared domains kept for free mailboxes | Separate domains, and separate servers with sending addresses of their own | Providers keep reputation per sending address and per sending domain. Keeping the lanes on separate domains means a problem on one lane's domains stays on those domains, and keeping free mailboxes on separate servers and addresses means a misused free mailbox does not touch the addresses paying customers send from. The free lane also has stricter sending limits of its own: see [Get a free sending mailbox](https://docs.warmerly.com/help/free-sending-mailbox). Transactional email (the messages your app sends, such as receipts and sign-in links) and Warmerly's own account emails do not use these lanes at all. They go out through a separate sending platform, where each workspace's transactional mail is kept apart from every other workspace's. ## How a new sending address earns volume When we add a sending address to a lane, it does not start with a full share of the mail. 1. **It is checked first.** Its name records must point both ways (the address names its server, and the server's name leads back to the address), and it must not be on a blocklist. Until it passes, it carries no customer mail. 2. **It starts small.** It begins with a small share of its lane's mail. 3. **It grows one step at a time, about once a day.** It only grows when there was enough mail to judge, the results at every receiving provider were healthy, it really used the share it already had, and it is not on a blocklist. 4. **It does not grow on age.** It never grows just because time has passed. An address that sits idle, or whose results slip, stays where it is. 5. **It has a ceiling.** Growth stops at a limit set for that address, and only a person on our team can raise it. Each address keeps its own track record and its own pace with each receiving provider. Gmail, Microsoft, Yahoo and Apple are each tracked separately, and all other providers together, so trouble at one provider first slows mail to that provider only. This is the same idea as warmup for a mailbox, applied to the servers' own addresses. For your mailbox itself, see [How warmup works](https://docs.warmerly.com/how-warmup-works). ## What we watch For every sending address, separately for each receiving provider: - **Bounces**: messages rejected because the address does not exist or cannot receive mail. - **Deferrals**: messages the receiving provider asks us to try again later. - **Refusals as spam**: messages the provider turns away because of the sender's reputation or the content, rather than because of the address. - **Spam complaints**: recipients pressing "report spam", when the provider reports it back to us. Most providers, Gmail included, never tell the sender who pressed "report spam", so a low count here does not prove nobody did. - **Blocklists**: whether any of our sending addresses appears on the public lists that providers consult. For each hosted mailbox you pay for or bought ready-warmed, and each workspace, we also watch the campaign mail it sends to the outside world: how much bounces, how much is refused as spam, and how many recipients report it. Warmup mail between Warmerly mailboxes does not count. The free mailbox has fixed, stricter limits instead (see [Get a free sending mailbox](https://docs.warmerly.com/help/free-sending-mailbox)). For your mailbox and workspace, each check needs enough mail to judge before it counts, and one spam report is not enough on its own, so one person pressing "report spam" does not slow your mailbox down. ## What we do when results slip The automatic steps slow sending down, and bring it back a step at a time once results are healthy again. Beyond that, the only volume they add is the slow growth of a healthy new address described above, up to its ceiling. **At one address, for one receiving provider.** If results at, say, Microsoft get worse at one address, that address slows its delivery to Microsoft. Mail to other providers carries on at the normal pace. Once results have been clean for a while, the normal pace comes back. **At one address, for everyone.** If an address appears on a blocklist, or its results at a provider are bad enough, it is slowed for every provider and taken out of use as soon as another healthy address can carry its mail. If the listing is on one of our own sending addresses, mail from the hosted mailboxes behind it is also held automatically, and it resumes by itself once the listing has cleared and the next checks stay clean. Otherwise a person on our team decides when an address comes back, and records why. **For one hosted mailbox you pay for.** Usually you first get an email saying results are slipping, while sending carries on as normal. If they keep slipping, the mailbox's campaign sending is slowed to about half of its usual daily volume. If the results are bad rather than slipping, it is slowed to about a quarter straight away, and if they are still that bad a day later, the mailbox comes off your campaigns until it recovers. **For a whole workspace.** When the problems are spread across a workspace's mailboxes, the same happens one level up: the workspace can be slowed, and if things do not improve, campaign sending is paused on every mailbox in it. Our team is told when that happens and may review the workspace. **Warmup keeps running.** Slowing or pausing campaign sending does not stop warmup, because warmup is what rebuilds a mailbox's reputation. **You are told.** We email you (unless you have turned off alert emails) when sending is slowed or paused. The mailbox page (and, for a workspace, the **Accounts** page) shows a banner saying what was measured and what helps. **It comes back by itself.** As the results stay healthy, sending is raised a step at a time, about a day apart, until it is back to normal. If our team is reviewing your workspace, it returns once that review is done. The details are in [Why did my sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused) ## What we do not do - We do not switch addresses to get around a block; we slow down, find the cause and recover. - The automatic system never adds, buys or swaps sending addresses. Adding an address to the network is a decision a person on our team makes; the system only starts it on a small share once it passes its checks. - Suspending a Warmerly account is a decision made by a person on our team. The one exception is the transactional email service, where repeated automatic pauses for abuse can end in the account being suspended. - Every change the sending network makes on its own is recorded with the evidence behind it, and our team can review it and undo it. ## How we protect your reputation from other customers - **Separate lanes.** Each lane uses its own domains, and free mailboxes are placed on separate servers, away from the paid lane's sending addresses. - **Every paid mailbox and workspace is judged on its own mail.** A customer whose campaign mail starts to bounce or draw complaints is slowed down mailbox by mailbox, and then across their workspace, as soon as there is enough mail to judge. - **Pace per provider.** Each sending address has its own pace with each receiving provider, so a provider that pushes back gets less mail from that address rather than more. - **A person before any suspension.** Accounts that keep causing problems are looked at by our team, and our [Acceptable Use Policy](https://warmerly.com/acceptable-use) sets out what is not allowed. ## What we promise Warmerly makes exactly four promises beyond "we try our best". The binding wording is in the Guarantees section of our [Terms of Service](https://warmerly.com/terms#guarantees); this is a summary of it. - **30-day inbox guarantee.** Warmup (paid outreach plans). Refund of that month's plan fee (1/12 of an annual fee) if a mailbox warming continuously for 30 days shows no placement improvement between its first test and one on/after day 30. Conditions: stayed connected with warmup on; both tests run in Warmerly; not if blocklisted for reasons unrelated to warmup or the account breaks the AUP; one refund per workspace; request within 14 days of the later test. - **You only pay for email that leaves us.** Transactional. An email that fails on our side and is never handed to the recipient's server doesn't count toward allowance or overage. Handed over then bounced still counts. - **Authentication, not inbox placement.** Transactional. No placement promise; every sending domain must pass SPF, DKIM and DMARC before it can send, and is re-checked automatically. - **99.9% monthly API availability.** Transactional. The service credit, what is excluded and how to claim are in the [Terms of Service](https://warmerly.com/terms#guarantees). Claims go to support@warmerly.com. ## See your own health in the app - [What do my mailbox's health score and status mean?](https://docs.warmerly.com/help/mailbox-health): the health score, the status badges and the banner on a mailbox page. - [How do I read the domain health card?](https://docs.warmerly.com/help/domain-health-card): your domain's DNS records and blocklist checks. - [How do inbox placement tests work?](https://docs.warmerly.com/help/placement-tests): where a real message from your mailbox lands. - [What if my domain or IP is on a blocklist?](https://docs.warmerly.com/help/blocklisted) - [Why did my sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused) ## Live status [status.warmerly.com](https://status.warmerly.com) shows, live, whether our mail servers, their reputation and the sending network are working, along with every other part of Warmerly. See [Is Warmerly down?](https://docs.warmerly.com/help/status-page) for how to read it and follow incidents. ## What we cannot control - **The receiving provider decides.** Whether a message lands in the inbox or in spam is decided by Gmail, Microsoft and the rest, not by us. Good infrastructure gives your mail a fair hearing; it cannot make a provider accept it. - **Trust takes time.** A new sending address, a new mailbox or a brand-new domain has to build a track record before providers trust it with full volume, and that cannot be hurried. - **Content and lists still matter.** A well-warmed address sending to an old or bought list, or sending spammy content, can still land in spam. The tips in [Why did my sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused) help with both. ## Questions ### Do you rotate IPs? Not to get around a block. Within a lane, mail is shared across that lane's sending addresses in proportion to how much trust each one has earned, so a newer address carries less. When an address runs into trouble, we slow it down and, if the trouble is serious, take it out of use as soon as another healthy address can carry its mail, and we find the cause. We do not bring in a fresh address to escape the problem. ### Do I share an IP with other customers? If your mailbox is hosted by Warmerly (OneMail), yes: it sends from the paid lane's sending addresses, which also carry mail for other customers' hosted mailboxes and, today, for the ready-warmed mailboxes we keep for sale. Each paid mailbox and workspace is still judged on its own results, and one that starts causing problems is slowed down on its own. Free mailboxes are placed on separate servers with addresses of their own, and have fixed, stricter limits instead (see [Get a free sending mailbox](https://docs.warmerly.com/help/free-sending-mailbox)). If you connected a mailbox from your own provider (Gmail, Microsoft 365 or your own mail server), it sends from that provider's addresses, not ours. ### Why was my sending slowed? One of the automatic protections above acted on your mailbox or workspace. The banner on the mailbox page says which one and what was measured, and [Why did my sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused) explains each one and how sending comes back. ### How long does a new mailbox take to warm up? A mailbox is fully warm after about two weeks, longer on a brand-new domain. You don't have to wait to launch: a campaign on a young mailbox starts with a small daily volume and climbs. See [How warmup works](https://docs.warmerly.com/how-warmup-works). ### Does Warmerly read my mail? To judge reputation, the sending network records the outcome of each delivery attempt and the recipient's domain, not what your messages say. It also keeps the address of the mailbox that sent each message and, when a provider reports that someone marked a message as spam, that person's address, so it can be taken off future sends. Warmup identifies warmup mail by the message identifiers of the messages it sent, and acts only on those messages. It does not open, move or reply to your other mail. Other features you switch on, such as the unified inbox, access your mailbox under our [Terms of Service](https://warmerly.com/terms) and are not part of warmup. See the [Warmup network terms](https://warmerly.com/warmup-terms). ## Related - [How warmup works](https://docs.warmerly.com/how-warmup-works) - [Why did my sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused) - [OneMail hosted mailboxes and domains](https://docs.warmerly.com/help/onemail-mailboxes) - [Deliverability checklist](https://docs.warmerly.com/guides/deliverability-checklist) --- # Plans, limits and allowances All prices on this page are **USD per month**. Annual billing is 10x the monthly price, so two months are free. The live plan cards are always at [warmerly.com/pricing](https://warmerly.com/pricing); this page explains how the numbers behave. ## What each plan costs and includes | | Free | Starter | Growth | Agency | | --- | --- | --- | --- | --- | | Price | $0 | $19 | $49 | $179 | | Mailboxes | 1 | 5 | 25 | 100 | | Active campaigns | 1 | 5 | 25 | Unlimited | | Leads per campaign | 500 | 2,500 | 25,000 | 100,000 | | Active prospects | 500 | 5,000 | 50,000 | 250,000 | | Campaign sends | 100/mo | Unlimited | Unlimited | Unlimited | | Warmup emails | Unlimited | Unlimited | Unlimited | Unlimited | | Email verifications | 250/mo | 5,000/mo | 25,000/mo | 150,000/mo | | Email lookups | 50/mo | 1,000/mo | 10,000/mo | 100,000/mo | | LinkedIn lookups | 50/mo | 1,000/mo | 10,000/mo | 100,000/mo | | Lead exports | 100/mo | 500/mo | 5,000/mo | 50,000/mo | | Placement tests | 3/mo | 5/mo | 25/mo | 100/mo | | AI credits | 0 | 100/mo | 500/mo | 2,500/mo | | API access |: | (|) | Yes | Warmup is included on every plan and is never metered. **Free is a real plan, not a countdown.** No card, no expiry — you can stay on it indefinitely. Its 100 campaign sends per month exist as an abuse guard, not as a trial clock. **Paid tiers include a 7-day free trial.** A card is required to start it, nothing is charged until day 8, and you can cancel before then. During a trial the monthly allowances are Starter's regardless of which tier you are trialling, while the mailbox and campaign ceilings are the trialled tier's own. **API access is Agency-only.** See [Authentication](https://docs.warmerly.com/authentication) and [API keys](https://docs.warmerly.com/keys). ## Sending is not metered on paid plans Paid plans are sold on **mailboxes and leads**, not on emails sent. There is no monthly send quota to run out of on Starter, Growth or Agency. ### How many emails can I send per day? What actually bounds your volume is arithmetic: mailboxes x each mailbox's own daily sending limit (30/day by default, lower while a mailbox is still ramping). Five mailboxes at 30/day is roughly 150 sends a day, whatever the plan says. If you need more volume, the answer is more mailboxes or higher per-mailbox limits on warm mailboxes, not a bigger send quota. ## What LinkedIn costs (sold separately) LinkedIn is **$19/month per connected account** (US dollars; £15 or €17 where you are billed in pounds or euros), on top of your base plan, with no free trial. It is not bundled into any tier. One slot covers that account's LinkedIn warmup and its LinkedIn campaign steps. Buying more than one is cheaper per account. A **3-account pack** is **$49/month** ($16.33 each; £39 or €45) and a **5-account pack** is **$75/month** ($15 each; £59 or €69). A pack is one subscription: its accounts begin, renew and end together, so it cannot be partly cancelled. LinkedIn accounts and packs are charged immediately and are **non-refundable**. You can cancel at any time and keep access to the end of the period you have paid for. ## Three different kinds of limit They behave differently, and the difference is usually what someone is actually asking about. **1. Monthly allowances** — verifications, email lookups, LinkedIn lookups, lead exports, placement tests, AI credits, and Free's campaign sends. These count month-to-date against a ceiling and **reset on the 1st**. They do not roll over. A lookup or verification that fails or returns nothing is **not charged**: the allowance is only debited when the action produced a result. **2. Capacity limits** — mailboxes, active campaigns, active prospects. These are a live count, not a monthly total, and there is nothing to reset: disconnect a mailbox and the slot is free immediately. **3. Per-item ceilings** — leads per campaign. Checked when leads are imported. Splitting a big list across several campaigns is a perfectly legitimate way to work within your plan. Everything above is visible in the app at **Settings → Usage & limits**, with each monthly allowance also shown on the tool that spends it (Verify, Email Finder, Find leads, Accounts, Campaigns). **Settings → Billing** is where you change plan, and **Settings → Billing → Manage billing** opens the Stripe portal for invoices, payment method and cancellation. ## What happens when you hit a limit Nothing is deleted, ever. The enforcement is deliberately boring: - **Connecting a mailbox beyond your allowance** is refused at that moment, with an explanation. Nothing is charged and nothing is lost. - **Starting more campaigns than your plan allows** is refused the same way. Drafts are unlimited, the limit is on campaigns actively running. - **Importing more leads than the per-campaign ceiling** is refused at import. - **A workspace that ends up over its plan** (for example after a downgrade) gets a grace period, shown as a countdown banner in the dashboard. Everything keeps running normally during it. When it expires, nothing is removed: campaign sending and warmup **pause** until the workspace is back inside its limits or on a bigger plan. There are always two ways back inside a limit, upgrade, or reduce (remove unused mailboxes, pause campaigns). Both are equally valid. ## Billing lock If a workspace has no active subscription it can need, or has stayed over its limits past the grace period, the dashboard redirects to a billing screen until that is resolved. While a workspace is locked: - campaign sending, email warmup and LinkedIn warmup are all **suspended**; - campaigns are **not** cancelled or reset; - everything resumes by itself within a few minutes of the workspace subscribing or dropping back under its limits. A few routes stay open while locked (your accounts, campaigns and settings) precisely because the advice for clearing a lock ("pause a campaign", "remove a mailbox") needs those pages. ## See also - [How warmup works](https://docs.warmerly.com/how-warmup-works): why sending volume and warmup are separate questions - [FAQ](https://docs.warmerly.com/faq): the short answers - [Errors & rate limits](https://docs.warmerly.com/errors): API-side quotas, which are separate from plan allowances --- # Troubleshooting ## DKIM shows "missing" but the record exists This is usually a **selector** problem, not a DNS problem. Warmerly checks DKIM by trying a list of common selector names (`default`, `google`, `k1`, `s1`, `mail`, and others) against your domain's DNS. It cannot discover an arbitrary selector on its own. If your provider uses something that is not on that list, common with self-hosted mail, Zoho, and custom ESP setups, the check reports **none** even though the record is genuinely published and your mail is genuinely signed. **Fix:** open **Accounts → your mailbox → Settings → DKIM selector**, enter your real selector, and re-check DNS. If you do not know it, your provider's DKIM setup page (or the `selector._domainkey.yourdomain.com` TXT record in your DNS panel) has it. A "missing DKIM" warning in Warmerly is not by itself proof your DKIM is broken. Check the selector before changing anything in DNS. Full walkthrough: [Setting up DKIM](https://docs.warmerly.com/guides/dkim). ## Microsoft 365: SMTP username or password failed, but OAuth reconnected fine An OAuth reconnect that succeeds followed by an SMTP authentication failure is almost never a password problem. Two causes, in order of likelihood: **1. Mailbox identity mismatch.** Warmerly sends over SMTP/IMAP using XOAUTH2 (it does not send through Microsoft Graph), and Exchange requires the username to be the mailbox's **primary SMTP address**. That address is allowed to differ from the Microsoft sign-in address (the UPN), and when it does, authentication fails with a credentials-shaped error. Check the address shown on the mailbox in its settings, correct the SMTP/IMAP username if it is not the primary address, and reconnect. A reconnect re-reads the real mailbox address from Microsoft. **2. SMTP AUTH disabled tenant-wide.** Microsoft 365 can have SMTP AUTH turned off for the whole tenant (and it is off by default on newer tenants), which produces the same error for every mailbox no matter what you type. A tenant admin has to enable SMTP AUTH for the mailbox or the organisation. **Aliases, shared and delegated mailboxes** are supported: set the SMTP/IMAP username to that mailbox's address, as long as the signed-in user has Send As or Full Access rights on it. ## Outlook / Microsoft 365: "We could not finish connecting your Outlook account" The one-click Microsoft sign-in ends on this page when something stops it. The heading under it says which step failed: | What the page says | What happened | What to do | | --- | --- | --- | | **Connection cancelled** | The Microsoft permission screen was closed or declined | Start again and click **Accept** on every screen | | **Session expired** | The sign-in took too long, or was finished in a tab that was reopened or navigated back | Start again from **Accounts → Add** in a fresh tab and finish it in one go | | **Provider hiccup** | Microsoft did not return a valid token | Usually temporary, wait a minute and retry | | **Already connected** | That mailbox is already in your workspace | Manage it from **Accounts**; to reconnect it, open the mailbox and use **Reconnect** | | **Sign in and try again** | The browser that finished the sign-in was not signed in to Warmerly | Sign in to Warmerly in this browser, then start the connection again | | **No access to that mailbox** | The connection was for a mailbox that belongs to another workspace | Switch to the right workspace, or start from the mailbox you want to connect | | **Could not finish connecting** | The last step failed for a reason we could not identify | Retry once from a fresh browser tab (a reopened tab carries a stale security value). If it still fails, add the mailbox with SMTP/IMAP details instead. That route does not use sign-in at all | **Microsoft shows "Need admin approval" before you ever get back to Warmerly.** Your organisation only lets an administrator approve new apps. Ask your Microsoft 365 admin to approve Warmerly, they sign in with the same button and tick **Consent on behalf of your organization**: or to allow users to consent to apps. After that, everyone in the organisation can connect their own mailbox. If the connection succeeds but sending then fails with an SMTP username or password error, see the Microsoft 365 section above: that is SMTP AUTH or the primary-address mismatch, not the sign-in. ## Google Workspace: app passwords "not available for your account" Gmail and Google Workspace mailboxes connect with a Google app password. On a Workspace user, the app passwords page often refuses with *"The setting you are looking for is not available for your account"* / *"Your account doesn't support the setting you're trying"*. The cause is almost always that **2-Step Verification is not on for that user**: and on Workspace an admin has to allow it first (Admin console → Security → Authentication → 2-Step Verification → **Allow users to turn on 2-Step Verification**, methods **Any**, not "Only security key"). Then the user turns 2-Step Verification on and the app passwords page works. Full steps and the rarer causes (Advanced Protection, a restricted org unit): [Connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection#google-workspace-the-setting-you-are-looking-for-is-not-available-for-your-account). ## A mailbox is paused or shows as unreachable Warmerly pauses a mailbox when its provider stops accepting connections, an expired password, a revoked OAuth grant, a provider-side block, or a host that went down. Paused mailboxes are retried automatically on a schedule, and a mailbox that starts answering again is returned to service without you doing anything. If it stays paused, reconnect it from **Accounts → the mailbox → reconnect**, and check the provider side first: a changed password or a revoked app grant invalidates the stored credentials even though nothing in Warmerly changed. A mailbox paused for **reputation** reasons is different: it is taken out of campaign sending but **keeps warming up**, and it is returned to campaigns automatically once it recovers. That is intentional, a mailbox with a reputation problem is the last one that should stop building reputation. A mailbox can also be paused **as a whole, warmup included**, when its health score stays under 60 for two days. It resumes by itself after about three days. See [Sending slowed or paused](https://docs.warmerly.com/help/sending-slowed-or-paused). ## A campaign is not sending Work down this list; it is roughly the order of how often each one is the cause. 1. **The campaign is not actually live.** A draft sends nothing. Check its status on the campaign page. 2. **No sending mailbox is attached**, or every attached mailbox is paused. 3. **Per-mailbox daily limits are already used up.** A mailbox's daily limit is shared across every campaign it sends for, so two campaigns on one mailbox do not each get the full allowance. 4. **The mailbox is still ramping**, so its effective daily figure is below its limit. 5. **Sending window and schedule.** Nothing goes out outside the campaign's configured days and hours. 6. **The workspace is billing-locked or past its limit grace period**: sending and warmup are both suspended until that clears. See [Plans and limits](https://docs.warmerly.com/plans-and-limits). 7. **Leads are suppressed or invalid.** Addresses on the [suppression list](https://docs.warmerly.com/suppression) are never sent to, and that is working as designed. ## Placement tests A placement test sends real probe emails from your mailbox to seed addresses across providers and reports where each landed: inbox, promotions, or spam. It is the most direct answer to "is this mailbox healthy." - Run it from **Accounts → the mailbox → Health tab → Inbox placement card → Run new test**. See [How inbox placement tests work](https://docs.warmerly.com/help/placement-tests). - Each test spends one of your monthly placement tests (see [Plans and limits](https://docs.warmerly.com/plans-and-limits)). Tests that fail to run do not spend one. - Results are a snapshot of that mailbox, that day, at those providers. One promotions placement is not an emergency; the same mailbox landing in spam repeatedly is. **If a test lands in spam:** check DKIM, SPF and DMARC are all passing ([guides](https://docs.warmerly.com/guides)), confirm the mailbox has actually finished warming up, and look at the content you are sending, spam-word-heavy copy, a bare link, or a brand-new tracking domain will sink a technically perfect mailbox. ## Replies are not showing in the inbox Warmerly reads replies over IMAP on a schedule, so a reply that arrived seconds ago may not be there yet. Beyond timing: - the mailbox must be connected and not paused, because IMAP errors stop reads as well as sends; - warmup traffic is classified separately from real mail, so warmup replies do not clutter your inbox view by design; - only replies from people who are leads in your campaigns are graded (Interested, Not relevant, Spam). Other mail stays Unclassified and shows only under **All**, so check the filter you are looking at before concluding a reply is missing. See [How the Inbox works](https://docs.warmerly.com/help/inbox). See the [Inbox API](https://docs.warmerly.com/inbox) for the same data over HTTP. ## Still stuck Ask Warmi in the chat widget (bottom right of the app and of these docs). It can read your own mailbox, campaign and plan status, and can hand the conversation to a human when the answer is not in the docs. --- # Use Warmerly with AI (MCP) Warmerly runs a [Model Context Protocol](https://modelcontextprotocol.io) server, so an AI assistant you already use (Claude, ChatGPT, Claude Code, Cursor, or any other MCP client) can look things up in your Warmerly workspace directly: your mailboxes and their health, campaigns, leads, inbox conversations, deliverability checks and transactional email, all without you copy-pasting data back and forth. You sign in once with your normal Warmerly login; after that the assistant asks Warmerly, not you. **Available on every plan, including Free.** There's no separate API key or add-on required to connect, just your Warmerly account. ## Server URL ``` https://app.warmerly.com/api/mcp ``` Every client below connects to this one URL. ## Connect ### claude.ai 1. Go to **Settings → Connectors → Add custom connector**. 2. Paste `https://app.warmerly.com/api/mcp` as the server URL. 3. Sign in with your Warmerly account when prompted. ### ChatGPT 1. Go to **Settings → Apps & Connectors**, and turn on **Advanced** (or **Developer mode**) if you don't already see an option to add an MCP server. 2. Add a new MCP server and paste `https://app.warmerly.com/api/mcp` as the URL. 3. Sign in with your Warmerly account when prompted. Connector availability depends on your ChatGPT plan, if you don't see the option, it isn't enabled on your current plan. ### Claude Code ```bash claude mcp add --transport http warmerly https://app.warmerly.com/api/mcp ``` Then run `/mcp` inside Claude Code and follow the prompt to sign in with your Warmerly account. ### Cursor Add this to `~/.cursor/mcp.json`: ```json { "mcpServers": { "warmerly": { "url": "https://app.warmerly.com/api/mcp" } } } ``` Cursor will prompt you to sign in with your Warmerly account the first time it calls a tool. ## Claude plugin and skills The connection gives an assistant Warmerly's tools; skills teach it how to use them well. Warmerly publishes four, each a workflow rather than a list of tools: - **launch-outreach-campaign:** from your ideal customer to a verified lead list, a sequence that follows cold-email best practice, a readiness check and a launch. - **deliverability-doctor:** why mail lands in spam or bounces (mailbox health, SPF, DKIM, DMARC, MX, blocklists, placement tests) and exactly what to fix. - **reply-triage:** separate real replies from autoresponders and unsubscribes, draft answers, and suppress anyone who asked to be left alone. - **transactional-email-setup:** verify a sending domain for app email and check delivery. Every skill asks before bulk sends, launches or replies unless you tell it it may act on its own, and your plan limits and suppression list apply exactly as in the dashboard. The plugin is open source at [github.com/WarmerlyApp/claude-plugin](https://github.com/WarmerlyApp/claude-plugin). **Claude Code** installs the server and all four skills as one plugin: ```bash /plugin marketplace add WarmerlyApp/claude-plugin /plugin install warmerly@warmerly ``` Then run `/mcp` and sign in. (Already connected with `claude mcp add`? The plugin adds the same server, so you can remove the manual one.) **claude.ai:** add the connector as above, then upload each skill's `.zip` under **Settings → Capabilities → Skills**. To build the zips, clone the plugin repo and run `node build-skill-zips.mjs` (Node 18+, no dependencies); they land in `dist/`. Ready-to-paste configs for every other MCP client (VS Code, Windsurf, Codex CLI, Gemini CLI and more) are in [github.com/WarmerlyApp/mcp](https://github.com/WarmerlyApp/mcp). ## What happens when you sign in Signing in opens the normal Warmerly login (or lets you use an existing session), then a consent screen where you choose how much of your account that connection gets: - **One workspace** (the default). Every tool call from that assistant is scoped to the workspace you picked. It can't see or touch your other workspaces. - **All my workspaces.** The assistant can list every workspace you belong to and switch between them (`list_workspaces`, `switch_workspace`). It acts in one workspace at a time, starting in the one you picked, and the name of the workspace is in every switch reply so it can check before it writes. New workspaces you create later are included. The screen only offers this when you have more than one workspace. You can see which kind each connection is, and revoke it, under Settings, Connected apps. ## Tools Agents can read your workspace and act in it: create and launch campaigns, add leads, reply to your inbox, verify and find email addresses, manage suppression, and send transactional email, the same guardrails below apply to every one of those actions. | Tool | What it does | | --- | --- | | `search_docs` | Search the Warmerly documentation for pages relevant to a question. | | `read_doc` | Read the full content of a Warmerly docs page by slug. | | `get_account_overview` | Snapshot of the workspace: plan, quota usage, mailbox/campaign counts, setup gaps. | | `list_workspaces` | The workspaces this connection can act in, and which one it is acting in now. | | `switch_workspace` | Move a connection made for all your workspaces to another one. A single-workspace connection refuses. | | `get_connect_mailbox_link` | Get the URL to connect a mailbox yourself (mailbox credentials never pass through an MCP client). | | `list_mailboxes` | List the workspace's connected mailboxes, their status and health. | | `get_mailbox_health` | A mailbox's daily health history plus its latest SPF/DKIM/DMARC/MX check. | | `set_warmup` | Turn warmup on or off for a mailbox. | | `check_domain` | Run a live SPF/DKIM/DMARC/MX check against any domain. | | `run_placement_test` | Send a placement test from a mailbox and score where it landed. | | `list_sending_domains` | List the workspace's transactional email sending domains and verification status. | | `list_transactional_emails` | List recent transactional emails, newest first. | | `get_transactional_email` | Get one transactional email and its delivery event timeline. | | `send_transactional_email` | Send one transactional email to a single recipient (up to 3 cc and 3 bcc) from a verified sending domain. Optional `idempotencyKey` (your own id for the send, e.g. an order number): a repeat call with the same key is not sent twice. Without it, the key is a hash of the call's arguments. | | `search_leads` | Search Warmerly's lead database with a natural-language query or structured filters. Returns company details and whether each has a contact email, not the address itself, use `add_leads_from_search` to put them in a campaign. | | `count_leads` | Count how many leads match a search, without fetching rows. | | `verify_email` | Check whether an email address is likely to be deliverable. | | `find_email` | Start a job to find an email address for a person or company. | | `get_find_email_result` | Poll a `find_email` job for its result. | | `suppress_emails` | Add addresses to the workspace's suppression list. | | `list_campaigns` | List the workspace's campaigns with status and send/reply counts. | | `get_campaign` | Get one campaign's settings, sequence steps and readiness to start. | | `create_campaign` | Create a new draft campaign. | | `set_campaign_sequence` | Set a campaign's sequence of send steps. Custom merge tags (anything beyond the built-in name, company and sender tags) must already exist on the campaign's leads, so add leads first. Editing a running campaign keeps leads on their current step, and removing a step that leads are sitting on is refused. | | `add_leads` | Add leads you supply (your own list, a CRM export) to a campaign. | | `add_leads_from_search` | Add every lead matching a lead-database search to a campaign; counts against your lead-export allowance. | | `prepare_campaign_launch` | Check a campaign is ready to send and get the link where you press Launch or Resume yourself. It never starts sending. | | `pause_campaign` | Pause a running campaign. | | `get_campaign_stats` | Get a campaign's send/open/reply/bounce numbers. | | `list_conversations` | List inbox conversations (email/LinkedIn/WhatsApp), newest activity first. | | `get_conversation` | Get one conversation's message timeline and any draft reply. | | `draft_reply` | Generate and autosave an AI-drafted reply, without sending it. | | `send_reply` | Reply to an existing conversation over email, LinkedIn or WhatsApp, only after you have approved the exact message. It cannot start a new conversation. Leave out the subject to reply in the thread ("Re: …"). | | `categorize_message` | Set an inbox message's category: `lead`, `not_relevant` or `spam`. | ## Guardrails Every action a connected assistant takes goes through the exact same checks as the dashboard, there is no separate, looser path for AI: - **Same plan limits, quotas and capacity as the dashboard.** A tool call is refused under the identical conditions a dashboard click would be, through the same underlying function, and spends the allowance of the workspace the connection belongs to. - **The billing lock applies.** If the workspace is locked (a payment is overdue, it's over its plan's limits, or no plan is chosen), every action that sends or changes something is refused. Reading still works, and so do the actions that help you get back under your limits: pausing a campaign, turning warmup off, suppressing addresses and categorizing messages. A deleted workspace allows no actions until it is restored. - **The suppression list is enforced.** An AI-sent reply or campaign send never reaches an address that unsubscribed or bounced, the same as a human-sent one. - **Replies respect your mailbox's health.** `send_reply` won't send from a mailbox that is paused, needs reconnecting, or has campaign sending paused while its reputation recovers, and each sending account can send at most 50 replies a day through connected apps. - **An assistant can never start sending.** `prepare_campaign_launch` checks readiness (no leads, no senders, an unsupported channel on the current plan) and returns a link; you review the campaign and press Launch or Resume in Warmerly. Nothing is mailed to anyone until you do. - **Rate limited.** 60 tool calls per minute per connection; sends (a reply or a transactional email) additionally share a tighter 20-per-minute budget per connection and 40 per minute across all your connections, so a runaway assistant can't blow through your sending reputation even if it can call tools freely. - **Every action is logged.** Everything that sends or changes something is recorded to the workspace's audit log with the connected app's name, so "what did the AI do" is always answerable. Reads are not logged. - **No passwords ever pass through the AI.** Connecting a mailbox, or anything else that needs a password or OAuth grant, always happens in the Warmerly dashboard itself. The assistant can at most hand you a link to open. - **Revocable any time.** Every connection shows up under **Settings → Connected apps**, where you can revoke it, the assistant loses access immediately. - **Scoped to the workspace you chose.** A connection can only ever see and act in the one workspace you picked at sign-in, never your other workspaces. ## Documentation for LLMs If you are building on the [REST API](https://docs.warmerly.com) with an AI coding assistant, or want a model to answer questions about Warmerly, give it the docs in a form it can read in one go: | URL | What it is | | --- | --- | | [docs.warmerly.com/llms.txt](https://docs.warmerly.com/llms.txt) | An index of every docs page, with a one-line summary and a link to its Markdown | | [docs.warmerly.com/llms-full.txt](https://docs.warmerly.com/llms-full.txt) | The **entire** documentation (guides and the full API reference) as one Markdown file | | `docs.warmerly.com/.md` | Any single page as Markdown, e.g. [/campaigns.md](https://docs.warmerly.com/campaigns.md) or [/authentication.md](https://docs.warmerly.com/authentication.md) | They are generated from these pages, so they are always current. Paste the `llms-full.txt` URL into Claude, ChatGPT or Cursor (or save the file into your project) and ask it to write your integration. ## Troubleshooting - **The assistant says it got a 401 / lost access.** The connection was revoked or its token expired, reconnect using the steps above. - **The assistant is looking at the wrong workspace.** A connection made for one workspace stays in it. Reconnect and choose **All my workspaces** at the consent screen, then ask the assistant to switch workspace. Or reconnect and pick the other workspace, and keep both connections. --- # How do I find leads with Find leads? Open **Prospecting > Find leads** in the sidebar (the page is at `/leads`). Type a sentence describing the companies you want, such as "dental practices in the UK", and press **Find these companies**. Warmerly turns the sentence into filters, shows you the matching companies, and lets you export them as a CSV or add them to a campaign. **Searching is free.** Only exporting a CSV and adding leads to a campaign use your monthly lead allowance. The companies come from Warmerly's own database, built by reading the public websites of businesses. They are companies with a published way to contact them, not a list of named individuals. For the API version of the same search, see [Leads API](https://docs.warmerly.com/leads). ## Search with a sentence 1. Open **Find leads**. The first screen is a single box. 2. Describe who you want in your own words. Business type and place work best, for example "restaurants in London" or "accountants in Manchester". 3. Press **Find these companies** (or Enter). 4. Warmerly shows what it understood as a row of chips (for example the business type and the location), then the matching companies underneath. Under the chips there is a box for refining the search, for example "only ones hiring". Each chip has a remove button, and removing a chip is the same as clearing that filter in the panel below. ### What the sentence can and cannot express - It can express the same things the filter panel has: keywords, country, town or city, business type, the technology a website uses, email provider, company size, founding year, and the company signals listed below. - Things Warmerly does not hold, such as revenue, funding or ratings, cannot be searched. They show up as greyed, struck-through chips labelled "Not in our data, so it was not applied", so you can see what was ignored rather than assuming it was applied. - The filter panel holds one business type. If your sentence names several, the first is used and the others appear as not-applied chips. - A founding-year range is only applied if your sentence actually mentions one. - If the AI part is unavailable or cannot make sense of the sentence, Warmerly falls back to a plain keyword search and the chip row says "searched by keyword". Nothing is lost, you just get keyword matching instead. - Describing a search is free and does not use an AI credit. You can describe up to 60 searches an hour. If you hit that, wait a little and try again, or use the filters. ## Search with filters Press **Use filters instead** on the first screen, or use the filter panel that sits above the results. Every control narrows the results; none of them adds companies back. | Control | What it does | |---|---| | **Keywords** | Free-text search, for example "wedding photographer". | | **Country** | Limits to one country (default **Anywhere**). | | **Business type** | Pick from the grouped list (default **Any business type**). | | **Reachable by** | **Email address** (the default), **Contact form** or **LinkedIn page**. Every result has that way in. | | **Website uses** | Limits to companies whose site uses a technology you tick. | | **Email provider** | Limits to companies whose mail is hosted by a given provider. | | **Town or city** | For example "Manchester". | | **Company size** | A size band. | | **Founded between** | A from and to year. | | **Company signals** | **UK-registered**, **Hiring now**, **Has a phone number**, **VAT registered**, **Has a contact form**. | There is no way to search for companies with no contact route at all: every option under **Reachable by** guarantees one. Only the **Email address** option produces results you can add to an email campaign, because a campaign lead is an email address. ## Reading the results - **The count.** Above the table Warmerly says how many companies match. For narrower searches this is an exact number ("46,695 companies match"). For very broad searches it cannot count them all quickly, so it shows a rounded estimate ("roughly 450,000 companies match"). The estimate tends to be lower than the true number. - **The table** shows Company, Location, Business type, Contact email and Data. Open a row for more detail, such as address, phone, other email addresses, social pages, company and VAT numbers, size, founding year, whether they are hiring, website technology and when the company was **Last checked**. - **Business type** marked "Likely" is our best guess from the company's own website text, not something the company stated. - **Rows per page** is 50 or 100, and **Load more** fetches the next page. - **Sorting** by a column header reorders only the rows already loaded, not every match. The page says "sorted within the loaded rows" when this applies. - **What we hold on these companies** is a set of bars for Email, Phone, Company no., Contact form, LinkedIn and Country. For big result sets it is measured on a sample of the matches, and says so. Check it before you commit: a segment can be nearly all email but have almost no phone numbers. Company size and founding year are only known for companies that publish them, so filtering on them can shrink a search sharply. ### When almost nothing matches If a search returns very few companies, Warmerly offers ways to widen it, and shows how many companies each would return before you click, for example searching a whole country instead of one town, or any company size. If nothing matches at all, it may widen the search for you and say so in a banner ("Nothing matched that exactly. We widened the search"), naming what it dropped. Use the chips to narrow it back. ## Export or add to a campaign Tick the companies you want. A bar appears at the bottom with the actions. - **Select all matching** appears when there are more matches than you have loaded. It selects everything that matches the current filters, not just what is on screen. - **Export CSV** downloads a file. It includes the company name, website, country, city, business type, contact email and all published emails, phone, address, social pages, company and VAT numbers, size, hiring flag, founding year and other details. Emails are the published company addresses, which are often shared inboxes such as info@. - **Add to campaign** opens a dialog. Pick a campaign, or choose **+ Create a new campaign...**, then press **Add leads**. If you arrived from a campaign's **Audience** tab, a banner says which campaign you are building and the campaign is preselected in the dialog. ### What adding to a campaign does - Only companies with a contact email are added. If you selected companies found under **Contact form** or **LinkedIn page**, the dialog tells you they have no email and suggests exporting them to work by hand. - Duplicates already in the campaign are skipped. - Addresses that fail a quick free check (no working mail server, disposable domains, invalid format) are not added, so the number added can be lower than the number you selected. Risky and uncertain addresses are still added and marked. - Your own **Settings > Do not contact** list is applied, so anyone on it is skipped. Separately, companies that have asked to be removed from Warmerly's database never appear in search at all. - The campaign's per-campaign lead limit still applies (see [Plans & limits](https://docs.warmerly.com/plans-and-limits)). ## What it costs Searching, counting and describing a search never use your allowance. Each lead exported to CSV, and each lead actually added to a campaign, counts once against your **monthly lead allowance**, which resets on the 1st. Leads that are skipped or not added are not charged. The allowance is shown as a chip at the top of the page and in **Settings > Usage & limits**. See [Lead credits, lookups and allowances](https://docs.warmerly.com/help/prospecting-allowances) and [Plans & limits](https://docs.warmerly.com/plans-and-limits) for the size of the allowance on your plan. If an export would go past what is left of your allowance, the file stops at the allowance and Warmerly says so, rather than pretending it finished. Exports have no other row limit. Adding to a campaign takes at most 10,000 leads per click. ## Common problems - **"Lead export limit reached for this month."** You have used your monthly allowance. Check **Settings > Usage & limits**. You can buy more with credits there, upgrade, or wait for the reset on the 1st. - **Nothing matches my sentence.** Remove the most specific chip first (usually the town or company size). The suggestions under the results show how many companies each widening would return. - **The count differs from what I exported.** The count is measured before you act. At export time opted-out companies are removed again and rows without a contact address are dropped, so the file can be smaller. - **I searched by Contact form and Add to campaign added nothing.** Campaigns send email, so they need an email address. Export those rows to CSV instead. - **Too many searches in a row.** Wait a minute and try again. ## Related - [How do I import leads from a CSV?](https://docs.warmerly.com/help/import-leads-csv) if you already have a list - [How do I find someone's email address?](https://docs.warmerly.com/help/email-finder) for a specific company or person - [How do I check whether an email address is valid?](https://docs.warmerly.com/help/email-verification) - [How do I launch my first campaign?](https://docs.warmerly.com/help/launch-first-campaign) --- # How do I find someone's email address? Open **Prospecting > Email finder** in the sidebar (`/email-finder`). Enter a company website, domain or LinkedIn URL, or a person's name plus their company, and press **Find email**. Warmerly searches for the best address it can find, checks it, and shows the address with a status and a confidence score. A lookup only counts against your monthly email lookup allowance when an address is actually found. For the developer version, see the [Email Finder API](https://docs.warmerly.com/email-finder). ## Look up one address 1. Open **Email finder** and stay on the **Single lookup** tab. 2. Choose how to search: - **By domain**: type a website, domain or LinkedIn URL, for example `acme.com` or `linkedin.com/company/acme`. - **By person**: enter **First name**, **Last name** and **Company or domain**. At least a first or last name is required. 3. Press **Find email**. A progress bar shows the stages: Queued, Finding company, Searching for email, Checking email, Done. 4. The result shows the address, a status badge, a confidence percentage, and how it was found ("via site scrape", "pattern guess", "provider" or "mx only"). If the answer takes more than about two minutes, Warmerly tells you it is still running in the background. It will appear under **Recent lookups** when it finishes. A lookup that was seen before can come back instantly. If nothing is found you will see "No email could be found", with a shortcut to try the other search mode. A domain search looks for the company's published addresses; a person search also tries likely address patterns for that individual. ## What the result means **Status** says whether Warmerly could confirm the address works: | Status | Meaning | |---|---| | **Verified** | Strong evidence the address is real and accepts mail. | | **Probable** | Likely correct but not fully confirmed. Safe to try, with a slightly higher chance of a bounce. | | **Unverified** | Found, but Warmerly has not been able to check whether it works. | | **Invalid** | The address bounced or does not exist. | | **Not found** | No address could be found. | **Confidence** is a score from 0 to 100. Green (80 and above) is the safest to send to, amber (50 to 79) is a reasonable guess. The score depends on how the address was found and whether it could be confirmed: - An address **read from the company's own website** scores highest, because it was published by them. - An address from a **data provider** ranks next. - A **pattern guess** (for example first.last at the domain) starts lower and needs confirmation to reach a high score. - On domains that accept mail for any address (catch-all), guessed addresses are capped at a middling score, because a mail server that says yes to everything proves nothing. For a stronger answer on an uncertain address, run it through [Email verification](https://docs.warmerly.com/help/email-verification). ## Look up a list 1. Switch to the **Bulk upload** tab. 2. Paste one domain or LinkedIn company URL per line, or press **Upload CSV / TXT**. 3. Warmerly shows how many will be queued and how many lines were skipped (lines with no domain in them). Press **Queue N lookups**. 4. You are taken to the batch page, which shows progress and results as they arrive. Bulk lookups are domain based: one company per line. To look up a named person, use the single lookup. Large lists are sent in groups of 1,000, and each group becomes its own batch. Every batch is saved and shows up in the [Data library](https://docs.warmerly.com/help/data-library). ## Work with the results Everything you look up appears under **Recent lookups** (25 at a time, **Load more** for the rest). - **Copy** an address with the copy button. - **Re-run** (the circular arrow) looks the company up again. If it finds an address it uses an email lookup again. - **Delete** (the bin) removes the entry after a confirmation. It cannot be undone. - **Batch** opens the batch a bulk lookup belongs to. - **Export** downloads all your lookups as CSV or Excel. - **Add to campaign** adds the found addresses as leads in a campaign. By default only **Verified** addresses are included; untick the box to include the caution-level ones (Probable, Unverified) too. Invalid and not-found rows are never added, and duplicates already in the campaign are skipped. ## What it costs Each lookup that **finds an address** uses one email lookup from your monthly allowance, which resets on the 1st. Lookups that find nothing, and lookups that fail, are not charged. A lookup answered instantly because the same company was recently searched still counts if it returns an address. Before a bulk list starts, Warmerly checks you have enough allowance left for the whole batch, counting any lookups from earlier batches that are still queued. If you do not, the batch is refused and nothing is queued. The allowance is shown as a chip on the page and in **Settings > Usage & limits**, where you can also buy more with credits. See [Lead credits, lookups and allowances](https://docs.warmerly.com/help/prospecting-allowances) and [Plans & limits](https://docs.warmerly.com/plans-and-limits) for the size of the allowance on your plan. ## What it cannot do - It cannot promise an address is right. It reports a status and a confidence so you can decide. Anything that is not **Verified** may bounce. - It finds addresses at a company. It does not read anyone's private inbox or contact details. - Some websites block automated reading, or only show their content after JavaScript runs. Those are harder, and an address found from a pattern will have a lower score. - A LinkedIn person URL is best-effort: if you have a LinkedIn account connected, Warmerly can read the person's name and company for a better guess. Without one it falls back to a weaker method. ## Common problems - **"No email could be found."** Try the other search mode, or check the domain is spelled correctly and is the company's own website rather than a social page. - **The lookup is stuck on a stage.** Leave the page. It keeps running and lands in **Recent lookups**. - **A message saying your email lookups are used up.** Your monthly allowance is spent. Buy more with credits in **Settings > Usage & limits**, upgrade, or wait for the 1st. - **Bulk upload skipped lines.** A line needs a dot to count as a domain. The page shows a sample of the lines it skipped. ## Related - [How do I check whether an email address is valid?](https://docs.warmerly.com/help/email-verification) - [How do I find leads with Find leads?](https://docs.warmerly.com/help/find-leads) for lists of companies - [Email Finder API](https://docs.warmerly.com/email-finder) --- # How do I check whether an email address is valid? Open **Prospecting > Email verification** in the sidebar (`/verify`). Type an address and press **Verify**, or switch to **Bulk upload** to check a list. Warmerly tells you whether the address is **Safe to send**, **Send with caution**, **Do not send**, or **Unknown**, with a confidence score and a plain reason. A standard check does not send a message to the address. For the developer version, see the [Verify API](https://docs.warmerly.com/verify). ## Check one address 1. Open **Email verification** and stay on the **Single check** tab. 2. Type the address (for example `name@company.com`) and press **Verify** or Enter. 3. Read the banner at the top of the result: the recommendation, a one-line reason, and the confidence score. 4. Press **Show details** to see the individual checks. If Warmerly remembers a recent result for the address, it shows that instantly and free, and a **Re-check** button appears to run a fresh check. ## What the recommendations mean | Recommendation | What it means | |---|---| | **Safe to send** | The mailbox is active. Send with confidence. | | **Confirmed** | Warmerly knows this mailbox is real from something that really happened (for example it is one of your connected mailboxes, or it replied to real mail). Stronger than any test. | | **Send with caution** | Looks valid but could not be fully confirmed, or it is a shared inbox, or the domain accepts every address. Reasonable to send, expect a higher chance of a bounce. | | **Do not send** | Bad format, a domain that cannot receive email, a disposable address, or a mailbox that does not exist. | | **Unknown** | The mail server blocked the check or timed out. Nothing could be concluded. | Behind those sit the underlying statuses shown in tables and exports: **valid**, **invalid**, **risky**, **catch-all** and **unknown**. - **Valid** with a high confidence becomes Safe to send. A valid address that is a shared inbox (info@, support@ and similar) becomes Send with caution, because it will not reach a specific person. - **Catch-all** means the company's mail server accepts mail for any address at the domain, so one exact address cannot be confirmed. Google Workspace and Microsoft 365 behave this way for outside checks, so many business addresses land here. It is a limit of what can be known from outside, not a fault with your list. - **Risky** means the domain has a mail server but the mailbox could not be confirmed. - **Unknown** means the check was blocked or unreachable. Ambiguity is never turned into Invalid: an address is only marked Invalid when there is hard evidence (bad format, no mail server, a disposable domain, or the server explicitly saying the mailbox does not exist). ### The checks under Show details **Format**, **Mail server reachable**, **Mailbox accepts**, **Catch-all**, **Disposable**, **Shared inbox**, **Free provider** (Gmail, Yahoo and similar), **Can receive email** (does the domain have mail records), and the mail **Provider**. If the domain looks like a typo of a well-known one, a "Did you mean" suggestion appears that you can click. ## Confirm an uncertain address with a test send When a single check comes back **Catch-all**, **Risky** or **Unknown**, a **Confirm with a test send** button appears. It sends one short automated message from one of your connected mailboxes to that address and watches your inbox for a bounce for a few minutes. - A bounce means the mailbox does not exist, and the result becomes **Do not send**. - No bounce means the address accepted the mail, and the result becomes confirmed valid. - The recipient does receive a short message titled "Deliverability check", so use it only on addresses you would be comfortable mailing. - It needs a connected mailbox that Warmerly can read the inbox of. Without one you will see "No usable warmup account found. Connect an account (with inbox access) to run a test send." - It is a real email from your mailbox, so it counts like any other send for that mailbox's reputation. Use it to settle a handful of ambiguous addresses, not a whole list. - It is not billed as a separate verification. - It cannot settle a true catch-all domain: such a server accepts the message and never bounces, so "no bounce" does not prove the mailbox exists. ## Check a whole list 1. Switch to the **Bulk upload** tab. 2. Paste addresses (one per line, or separated by commas), or press **Upload CSV / TXT**. 3. The page shows how many addresses are ready. Press **Start verification**. For very large lists (over 2,000) you are asked to confirm, because it uses part of your allowance and cannot be stopped once started. 4. Results fill in as they are checked. A batch can hold up to 50,000 addresses, and duplicates in the paste are removed. Uncertain answers (for example a server that asks Warmerly to try again later) are retried automatically a few times before being reported. For some uncertain addresses in a bulk list, Warmerly may also settle the answer with a real test message from a mailbox Warmerly operates itself. It is never sent from one of your mailboxes, and only within strict limits. Each batch is saved under **Recent batches** and in the [Data library](https://docs.warmerly.com/help/data-library), so you can come back to it. From the results you can: - **Export** as CSV or Excel (columns: Email, Recommendation, Status, Confidence, Reason). - **Add to campaign**. Only **Safe to send** addresses are included by default. Untick the option to also add **Send with caution** ones. **Do not send** and **Unknown** addresses are never added. ## What it costs Each address that gets a **fresh** check uses one email verification from your monthly allowance, which resets on the 1st. Results Warmerly already knows are free: a repeat check of the same address within its memory window, and any observed fact, costs nothing. Uncertain results are remembered for a shorter time than certain ones, so they are re-checked sooner. A check that is retried is only charged once it has a final answer. Before a bulk batch starts, Warmerly checks your remaining allowance covers the whole batch, counting addresses from earlier batches still in the queue. If not, the batch is refused and nothing is queued. Check **Settings > Usage & limits** (where you can also buy more with credits), see [Lead credits, lookups and allowances](https://docs.warmerly.com/help/prospecting-allowances), and [Plans & limits](https://docs.warmerly.com/plans-and-limits) for the size of the allowance on your plan. The quick checks that run when you import leads or add leads to a campaign (format, disposable domains, mail server present) are free and do not use this allowance. See [How do I import leads from a CSV?](https://docs.warmerly.com/help/import-leads-csv). ## What it cannot do - **It cannot guarantee delivery.** A valid mailbox can still bounce later, be full, or be deactivated tomorrow. Results are a snapshot. - **It cannot see inside catch-all domains** or resolve every Microsoft 365 or Google Workspace address. These show as Send with caution or Unknown, not as a false Valid. - **It cannot tell you the person is interested,** only whether the mailbox exists. - Checks are paced gently per mail server to avoid looking like address harvesting, so a big list of addresses at a single company is slower than a mixed list. ## Common problems - **Lots of "Send with caution".** Usually catch-all or shared inboxes. They are fine to send to in moderation, and a test send can settle single addresses. - **Unknown on an address that looks fine.** The receiving server blocked or timed out. Press **Re-check** later. - **The result changed after Re-check.** Re-check runs a fresh test, and mail servers change. If Warmerly has direct evidence about a mailbox (a bounce or a reply), that evidence is kept and is not overwritten by a re-check. - **A message about your verification allowance.** It is used up. Buy more with credits, upgrade, or wait for the 1st. ## Related - [How do I find someone's email address?](https://docs.warmerly.com/help/email-finder) - [How do I find leads with Find leads?](https://docs.warmerly.com/help/find-leads) - [Verify API](https://docs.warmerly.com/verify) --- # How do I summarize a prospect's website? Open **Prospecting > Website summary** in the sidebar (`/tools/website-summary`). Paste the address of a page, for example a prospect's About page, and press **Summarize**. Warmerly reads the page and writes two to three short, factual sentences about what the business does, who it serves, and any concrete specifics. Use them as research when you write a personal first line. It does not use your email lookup, verification or lead allowance. One thing to know first: **summaries are saved in your browser on this device**, not in your Warmerly account. See "Where your summaries are kept" below. ## Summarize one page 1. Open **Website summary** and stay on the **Single page** tab. 2. Paste a page URL into **Website URL**, for example `https://example.com/about`. 3. Press **Summarize** (or Enter). 4. The summary appears under **Saved summaries**. Use the copy button on the card to copy it. Use a specific page rather than only the home page when you can. An About or Services page usually gives a sharper summary than a home page made of slogans. ## Summarize a list 1. Switch to the **Bulk upload** tab. 2. Paste one URL per line, or press **Upload CSV / TXT**. Commas also separate URLs. 3. Warmerly shows how many were accepted and how many were rejected. Addresses without `https://` are accepted and completed for you, and duplicates are removed. 4. Press **Summarize N pages**. A progress bar counts them off. Pages are done one at a time, so a long list takes a while. Keep the tab open until it finishes. A page that could not be summarized is saved with the reason, so you can see which ones to retry. ## What the summary is, and is not - It is two to three plain sentences about what the page says. It is instructed to state only what the page shows, with no marketing language and no invented facts. If the page is thin or unclear, it says so in one sentence. - It only uses the page you give it. It does not browse the rest of the site or look the company up elsewhere. - It reads regular web pages (HTML or plain text). It cannot read PDFs, images or pages behind a login, and it only uses the readable text near the top of a long page. - It is a starting point for a personal line. Read it before you use it: a summary can miss what a page does not say, and it cannot tell you what the business cares about today. ## Where your summaries are kept Saved summaries live in **your browser's local storage on this device**. That means: - They appear in the [Data library](https://docs.warmerly.com/help/data-library) marked **Saved on this device**. - They do **not** follow you to another computer or browser, and they are not visible to your teammates. - Clearing your browser's site data removes them. **Clear** on the page removes them all after a confirmation. - Only the most recent 100 are kept. - Use **Export CSV** to keep a copy. The file has the columns URL, Summary, Status and Created at. ## What it costs Nothing is taken from your monthly lookup, verification or lead allowance. Summaries do count towards the daily limit on AI use for your workspace, which is shared with other AI features. If you reach it, the page says "You've hit today's AI usage limit. Try again tomorrow." ## Common problems - **"Couldn't read that page."** The page may block automated readers, need JavaScript to show its content, be unreachable, or not be a normal web page. Try a different page on the same site, such as the About page. - **"AI is temporarily paused" or "The AI model is temporarily unavailable."** Try again shortly. - **My summaries disappeared.** They were stored in the browser. Check you are on the same device and browser, and that site data has not been cleared. - **No valid URLs.** Each line needs a website address with a dot in it, such as `acme.com/about`. ## Related - [Data library](https://docs.warmerly.com/help/data-library), where saved summaries are listed alongside other tool results - [How do I launch my first campaign?](https://docs.warmerly.com/help/launch-first-campaign) - [How do I find someone's email address?](https://docs.warmerly.com/help/email-finder) --- # What is the Data library and where do my bulk results go? The **Data library** (**Prospecting > Data library**, `/tools/data-library`) is an index of the bulk jobs and saved results from Warmerly's prospecting tools. If you ran a big lookup or verification and want to find it again, this is the page. It does not hold the results itself: each row has an **Open** button that takes you back to the tool where the records live, and the records stay there. ## What appears in it | Source | What becomes a dataset | Opens | |---|---|---| | **Email finder** | Each bulk upload batch | The batch page under [Email finder](https://docs.warmerly.com/help/email-finder) | | **Email verification** | Each bulk verification batch | The batch page under [Email verification](https://docs.warmerly.com/help/email-verification) | | **Warmerly Link** | Each LinkedIn people import into a campaign | The campaign it was imported into | | **Website summary** | Each summary you saved | The [Website summary](https://docs.warmerly.com/help/website-summary) page | What does **not** appear: - **Single lookups and single verification checks.** They are listed on their own tool page under **Recent lookups** and **Recent verifications**. - **Find leads exports.** A CSV from [Find leads](https://docs.warmerly.com/help/find-leads) is a file you download. It is not stored as a dataset. - **Uploaded campaign CSVs.** Those go straight into a campaign's **Audience** tab. Each source shows up to the 100 most recent datasets. ## Read the table Each dataset row shows: - **Name.** The batch name (an unnamed batch is shown as "Email Finder batch" or "Verification batch"), the search query for a LinkedIn import, or the URL for a summary. - **Source.** Which tool made it. - **Status.** **Queued**, **Processing**, **Completed** or **Failed**. - **Records.** How many were processed out of the total, and for a LinkedIn import the campaign it went to. - **Created.** The date it was made. ## Find a dataset Use the search box (it searches names, campaign names and source), the **Source** dropdown (**All tools** or one tool) and the **Status** dropdown. If nothing matches, the page says so and suggests clearing the search or choosing a different source and status. An empty library means you have not yet run a bulk lookup, verification, LinkedIn import or website summary. The same link, **Data library**, appears in the results header of Email finder, Email verification and Website summary. ## Website summaries are stored differently Batches from Email finder and Email verification, and LinkedIn imports, are saved in your Warmerly account. **Website summaries are saved in your browser on the device you used**, so they appear in the Data library only on that device and browser, marked **Saved on this device**. They are not shared with teammates and they disappear if you clear site data. Export them to CSV from the Website summary page if you want to keep them. See [How do I summarize a prospect's website?](https://docs.warmerly.com/help/website-summary). ## Common problems - **A batch I ran is missing.** Check it was a bulk upload (single checks are not listed), and that you are in the right workspace. Only the newest 100 per source are shown, so an older one may need to be reached from its tool page. - **My website summaries are missing.** They live in the browser. Open the library on the device and browser where you created them. - **A batch is stuck on Processing.** Large batches take time and finish in the background. Open the batch to see how many have been processed, and leave the page open or come back later. - **Does the library use my allowance?** No. Looking at it is free. The allowance is used when a lookup finds an address or a verification runs, as described in [Lead credits, lookups and allowances](https://docs.warmerly.com/help/prospecting-allowances). ## Related - [How do I find someone's email address?](https://docs.warmerly.com/help/email-finder) - [How do I check whether an email address is valid?](https://docs.warmerly.com/help/email-verification) - [How do I summarize a prospect's website?](https://docs.warmerly.com/help/website-summary) --- # How do lead exports, lookups and verifications use my allowance? The tools under **Prospecting** in the sidebar each have their own monthly allowance, and they are separate from each other: **lead exports** (Find leads), **email lookups** (Email finder) and **email verifications** (Email verification). Searching and looking around is free. An allowance is only used when you take something away: a lead into a CSV or a campaign, an address that a lookup found, or a fresh verification result. Allowances reset on the **1st of every month** and do not roll over. This page explains what uses what. For the size of each allowance on your plan, see [Plans & limits](https://docs.warmerly.com/plans-and-limits) or the [pricing page](https://warmerly.com/pricing). This page deliberately does not repeat those numbers because they depend on your plan. ## What is free and what is not | Action | Uses an allowance? | |---|---| | Searching in **Find leads**, using filters, describing a search in words | No | | The match count and the "what we hold" bars in Find leads | No | | **Export CSV** in Find leads | **Yes.** One lead-export per row delivered | | **Add to campaign** in Find leads | **Yes.** One lead-export per lead actually added | | A single or bulk lookup in **Email finder** that **finds** an address | **Yes.** One email lookup | | An Email finder lookup that finds nothing, or fails | No | | A **fresh** check in **Email verification** (single or bulk) | **Yes.** One email verification per address | | A verification result Warmerly already remembers | No | | **Confirm with a test send** on an uncertain address | No separate charge | | **Website summary** | No email allowance. It uses the shared daily AI limit | | **Data library** | No | | Quick free checks when importing a CSV or adding leads to a campaign | No | | Importing your own CSV of leads into a campaign | No lead-export use | Two things to notice: - **You are never charged for a failure.** A lookup or verification that errors, times out or returns nothing is not counted. - **Skipped leads are not charged.** In Find leads, companies that are already in the campaign, are on your **Do not contact** list, have no email address, or fail the free format and mail-server check are not added and not counted. ## Where to see what is left - **On the tool page.** A small usage chip sits at the top of Find leads, Email finder and Email verification. It is only shown when that allowance is limited on your plan, so a plan with no ceiling shows nothing there. - **In Settings > Usage & limits.** Every monthly allowance in one place, together with plan limits such as mailboxes and your credit balance. This is the page that owns the full picture. The API equivalent is described in [Usage & limits](https://docs.warmerly.com/usage). ## When an allowance runs out Nothing is deleted. The next action that would use the allowance is refused with a message naming what ran out, and everything you already have stays. Searching in Find leads still works. You have three ways forward: 1. **Wait for the 1st.** The counter resets at the start of the month, not on your billing date. 2. **Buy a top-up with credits.** In **Settings > Usage & limits**, an allowance that is near or at its ceiling offers a credit top-up. A top-up is a block of extra units of that one allowance. Blocks you buy **do not expire** and do not reset on the 1st, and they are used after the monthly allowance is gone. Credits are only ever spent when you press the button. Nothing is bought automatically. 3. **Change plan.** See [How do I cancel or change my plan?](https://docs.warmerly.com/help/cancel-or-change-plan). If you hit the limit partway through, the action stops where the allowance ends. A CSV export stops at what you have left and tells you it did, rather than pretending to finish. Exports also draw on a credit-bought block if you have one, so an empty monthly allowance with a block still exports. ## Bulk lists and the "reserved" check For bulk Email finder and Email verification, Warmerly checks up front that your remaining allowance covers the whole list. It also counts anything from earlier bulk lists that is still waiting in the queue. If the whole list would not fit, it is refused and nothing is queued, so you are not left with half a batch. You are only charged as items finish, not when the list is submitted. ## Different kinds of limit Do not confuse these three, because they show up in different places: - **Monthly allowances** (this page): lead exports, email lookups, email verifications and a few others, resetting on the 1st. - **Capacity limits**: how many mailboxes and active campaigns you can have right now. Nothing resets. Removing one frees the slot immediately. - **Per-campaign lead limit**: how many leads one campaign can hold. Adding leads past it is refused, even if you have allowance left. Splitting a list across campaigns is fine. All three are covered in [Plans & limits](https://docs.warmerly.com/plans-and-limits). ## AI credits are a different thing Your **credits** balance (shown in **Settings > Usage & limits**) pays for AI features and for the top-ups above. Describing a search in Find leads in your own words is free and uses no credits. Website summary uses no credits either, though both count toward a daily limit on AI use for your workspace. ## Common problems - **"Lead export limit reached for this month."** Your lead-export allowance is used. See the three ways forward above. - **I exported fewer leads than I selected.** The file stops at your remaining allowance, and rows that no longer have a contact address or belong to a company that opted out are dropped at export time. The confirmation message says which. - **The chip says something different from the count I was expecting.** The chip shows the month so far. Leads added to a campaign and CSV exports both count towards the same lead-export allowance. - **A bulk list was refused.** It did not fit in what is left, counting lists already queued. Split it, top up, or wait. ## Related - [How do I find leads with Find leads?](https://docs.warmerly.com/help/find-leads) - [How do I find someone's email address?](https://docs.warmerly.com/help/email-finder) - [How do I check whether an email address is valid?](https://docs.warmerly.com/help/email-verification) - [Plans, limits and allowances](https://docs.warmerly.com/plans-and-limits) --- # How do I write an email sequence for a campaign? A sequence is the series of emails a lead receives, with waits in between. You write it on the campaign's **Sequence** tab (or on step 2 of the new-campaign wizard). Pick a template or start blank, add **Email** and **Wait** steps, and edit the copy. There is no Save button: every change saves by itself about a second after you stop typing, and a small status line shows "Saving" and then "Saved". ## Steps 1. Open **Campaigns**, click your campaign, then open the **Sequence** tab. 2. If the sequence is empty you see **Start your sequence**. Choose one of the templates: **Three-step cold intro**, **Two-touch follow-up**, **LinkedIn then email** or **Single send**. You can also **Copy from an existing campaign** and pick one of your other campaigns. Every step stays editable afterwards. 3. Edit each email's **subject** and **body**. Write plain text. Warmerly turns it into a simple email for you. 4. Use **Insert variable** on a field to put a tag such as `{{firstName}}` where your cursor is. The full list is in [Merge tags and custom variables](https://docs.warmerly.com/help/merge-tags). 5. Set each **Wait** step. It reads "Wait 3 days before the next step". The shortcut chips are 1d, 3d and 1w, and you can change the unit to hours. 6. Click **Preview** on an email step to see it rendered for a real lead (see below). 7. Launch from the campaign page when the sequence and the rest of the campaign are ready. See [How do I launch my first campaign?](https://docs.warmerly.com/help/launch-first-campaign). ## What Warmerly adds for you You write the message. On sending, Warmerly adds: - Your **mailbox signature**, if the mailbox has one set. The signature is HTML, so it is left out when the campaign is set to send plain text only. - An **unsubscribe link** in the footer. See [Unsubscribe links](https://docs.warmerly.com/help/unsubscribe-links). - Open and click tracking, only if you turned them on in the campaign's **Settings** tab. See [Open and click tracking](https://docs.warmerly.com/help/open-and-click-tracking). Sign off with `{{senderFirstName}}` rather than typing a name. A campaign can send from several mailboxes in rotation, and a typed name will disagree with the From name as soon as a second mailbox is added. ## Simple and Branching modes The sequence editor has two modes. **Simple** is a plain ordered list: add, reorder with the arrows, delete. **Branching** is a drag-and-drop canvas that adds a **Condition** step. A condition splits the path on what the lead did: opened, clicked, replied, or a timeout when none of those happen in the wait time you set. - The Simple and Branching switch appears once the sequence has at least three steps, or whenever the sequence already branches. - A sequence that contains a condition cannot be edited in Simple mode. The editor shows a notice telling you to switch to **Branching** instead of quietly flattening your branches. - Opened and clicked branches only fire if tracking recorded the open or click. With open tracking off (the default for new campaigns) an "opened" branch never triggers. Sequences can also include LinkedIn steps. This page covers email steps. A WhatsApp step can be added in the editor but a campaign that contains one cannot launch, see [WhatsApp outreach](https://docs.warmerly.com/help/whatsapp-outreach). ## Preview an email before it sends Each email step has a **Preview** control. It saves your sequence first, then renders that step for a lead with the lead's own name, company and variables filled in, and with the sending mailbox's details. You can search your audience and preview a specific lead, which is how you check the one with no first name or the odd company name. The preview also lists any tags that came out empty for that lead. That matters because a blank tag leaves a sentence that still reads like a sentence ("Hi , saw that is hiring"). If the step uses `{{ai_opener}}`, previewing writes a real opener and can use an AI credit. See [AI personalisation with the AI opener](https://docs.warmerly.com/help/ai-opener). ## Editing a campaign that is already running You can edit a live sequence. Leads already partway through keep their place, and changes apply to the steps they have not reached yet. You cannot delete a step that leads are currently waiting on. The editor refuses, puts the step back and shows a message. Remove it later, once those leads have moved past it. Pausing the campaign does not free the step. Rewording a step is always fine. ## Common problems **A tag shows a warning saying it "isn't a variable".** The tag does not match a built-in tag or a custom variable on your leads. It would send as blank text. Check the spelling, because tags are case sensitive. See [Merge tags and custom variables](https://docs.warmerly.com/help/merge-tags). **"Launch now" is blocked with a merge tag error.** Same cause. The launch check refuses a tag that exists on none of your leads. Fix it on the Sequence tab. **I deleted a step and it came back.** Leads are waiting on it. See the section above. **My email looks different from what I typed.** Line breaks become paragraphs and the signature and unsubscribe footer are added at the end. Use **Preview** to see the final result. ## Related - [Merge tags and custom variables](https://docs.warmerly.com/help/merge-tags) - [A/B testing subject lines and email copy](https://docs.warmerly.com/help/ab-test-email-copy) - [What stops a sequence for a lead](https://docs.warmerly.com/help/what-stops-a-sequence) - [Why does my campaign send fewer emails than my daily limit?](https://docs.warmerly.com/help/campaign-sending-schedule) --- # What merge tags and custom variables can I use in my emails? A merge tag is a placeholder in double curly braces, such as `{{firstName}}`, that Warmerly replaces with each lead's own value when the email sends. Use them in the subject and the body. The built-in tags are listed below, and any extra column on your leads (a custom variable) works as a tag too. The important rule: **a tag Warmerly does not recognise is replaced with nothing.** There is no error at send time, so a typo ships as an email with a hole in it. ## Built-in tags | Tag | What it becomes | |---|---| | `{{email}}` | The lead's email address | | `{{firstName}}` | The lead's first name | | `{{lastName}}` | The lead's last name | | `{{companyName}}` | The lead's company | | `{{senderFirstName}}` | First name set on the sending mailbox | | `{{senderLastName}}` | Last name set on the sending mailbox | | `{{senderName}}` | Full sender name (first and last name, else the mailbox display name, else its address) | | `{{senderEmail}}` | The sending mailbox's address | | `{{ai_opener}}` | A personalised opening line written for each lead. See [AI personalisation](https://docs.warmerly.com/help/ai-opener) | Notes: - Tags are **case sensitive**. `{{firstname}}` is not `{{firstName}}` and will send blank. - Spaces inside the braces are fine: `{{ firstName }}` works. - Tag names use only letters, numbers and underscores. - The sender tags come from the mailbox each email actually leaves from. If the mailbox has no sender name set, `{{senderFirstName}}` is blank, so set the name on the mailbox first. - Use `{{senderFirstName}}` for your sign-off instead of typing a name. See [How do I write an email sequence?](https://docs.warmerly.com/help/email-sequences). ## Custom variables Any extra column on a lead is a custom variable, and its column name is the tag. If your CSV has a column called `mail_setup`, write `{{mail_setup}}`. When you import a file on the **Audience** tab (**Import leads**), columns that are not mapped to email, name or company become custom fields. A header that is not valid tag syntax is cleaned up: characters other than letters, numbers and underscores become underscores, so a column named "Job Title" becomes `{{Job_Title}}`. The Insert variable menu shows the exact names your campaign has. If a custom variable has the same name as a built-in tag, the custom value wins. See [How do I import leads from a CSV?](https://docs.warmerly.com/help/import-leads-csv) for the import steps. ## What the editor flags On the **Sequence** tab, a tag that is neither built in nor a custom variable on your leads gets a warning border and a line under the field: "`{{domain}}` isn't a variable, it will send as blank text." Things worth knowing about that warning: - The editor knows your real custom variables, so a working custom tag is not called a typo. If the list of variables has not loaded, the editor says nothing rather than accuse a tag on no evidence. - **Insert variable** shows how many of your leads actually have a value for each tag, plus a sample. A tag that only 8 of 200 leads have is not a typo, but it is not one to build a sentence around either. - A tag that exists on only some leads is not flagged, because that is normal for a list you have partly enriched. Those leads get a blank in that spot. ## The launch check Starting a campaign runs a check that blocks the launch if a step uses a tag that exists on none of your leads. The check appears in **Launch readiness** on the Overview tab with a **Fix in Sequence** link. It does not catch a tag that exists on some leads only. ## Check a specific lead before you send Use **Preview** on an email step and pick the lead you are worried about (no first name, an unusual company). The preview lists tags that resolved to blank for that lead. On the **Audience** tab, open a lead's conversation to see the variables that lead carries and the upcoming emails written out for them. ## Common problems **My email says "Hi ," with no name.** The lead has no first name. Fix the value on the lead, or reword the greeting. Preview shows this before you launch. **A tag works in preview for one lead and not another.** The second lead has no value for it. Check the coverage numbers under **Insert variable**. **My CSV column does not show up as a tag.** Only columns imported as custom fields become tags, and the name is the cleaned-up version of the header. Look under **Insert variable** for the exact spelling. ## Related - [How do I write an email sequence?](https://docs.warmerly.com/help/email-sequences) - [AI personalisation with the AI opener](https://docs.warmerly.com/help/ai-opener) - [Campaign audience and the lead conversation view](https://docs.warmerly.com/help/campaign-audience) --- # How do I personalise every email with the AI opener? Put the tag `{{ai_opener}}` where the first line of your email should go, for example on its own line right after the greeting. When the email sends, Warmerly writes a short opening line for that specific lead, based on your campaign brief and a summary of the lead's website. You keep the rest of your copy and your call to action exactly as you wrote them. Each opener uses one AI credit. The opener is one or two sentences with no greeting and no call to action. Warmerly avoids the usual cold-email giveaways such as "I noticed" and "hope this finds you well", and does not open with compliments about the recipient's work. ## What it needs The Sequence tab shows a small checklist under the editor as soon as a step uses the tag. Each row links to where you fix it: 1. **A campaign brief.** Open the campaign's **Settings** tab and fill in **Personalization brief**: **Who you are (sender context)**, **What you pitch / core value**, **Your ideal customer (ICP)** and, optionally, **Tone**. Save it. The row's link is **Write it**. 2. **Research on the leads.** Warmerly reads each lead's website and keeps a short summary. On the **Audience** tab, the **AI research** panel shows how many leads are researched. Click **Generate** to research the leads that need it, or **Regenerate all** to redo them. You can open the **Review** list under the panel to read and edit what it found. Any lead not researched yet is researched at send time. The row's link is **Run it now**. 3. **Credits.** One AI credit per personalised email. The row's link is **Top up**, which goes to **Settings > Usage & limits**. Allowances per plan are in [Plans and limits](https://docs.warmerly.com/plans-and-limits). ## Steps 1. On the **Sequence** tab, click **Insert variable** and choose `ai_opener`, or type `{{ai_opener}}` on its own line after your greeting. 2. Write the brief (Settings tab), then run the research (Audience tab). 3. Use **Preview** on the step and pick a lead to see a sample opener. Preview writes a real opener and can use a credit each time you click it. It is representative, not the exact words a recipient will get, because the sent email is always written fresh. 4. Launch the campaign. ## Which website does it read? The website at the domain of the lead's email address, unless the lead has an explicit research URL. That matters when the email domain is not the business's site: a lead on a shared hosting address would be researched against the wrong site, and a lead on a free personal email provider has no site to research, so it cannot be personalised and is skipped. Leads added through the API can carry an explicit research URL (see the [Campaigns API](https://docs.warmerly.com/campaigns)). For imports, check whether the import screen offers a Website column to map. Summaries are kept for 30 days. ## What happens when the opener cannot be written Warmerly will not send an email that should have had a personal opening line and does not, because it would open on a blank line with no personalisation, which is worse than no email. So: | Problem | What happens | |---|---| | The lead's website cannot be read (some sites block automated visits, roughly 5% of a typical list) | That lead is marked **Skipped**. Everyone else carries on. | | No campaign brief, no credits left, or the AI service is unavailable | Sending for the whole campaign is held. Leads stay queued and nothing is lost. When you fix the cause (write the brief, top up credits), sending resumes by itself. | | The AI leaves a fill-in-the-blank placeholder such as "[Tool Name]" | That opener is thrown away, and the credit is refunded. | If no opener is generated, the credit is refunded. ## The launch check Starting a campaign that uses `{{ai_opener}}` runs extra checks: - **No brief** blocks the launch. Fix it on the Settings tab. - **More than 20% of your queued leads have no research** shows a warning you can accept. - **A live test of the AI service** runs when you press Start, and blocks the launch if the service is not answering. It uses a negligible amount of AI usage. ## Upcoming emails in the conversation view When you open a lead's conversation on the Audience tab, upcoming emails that use the tag show the marker "written when this actually sends". They never spend a credit just for being looked at. ## Common problems **Leads are Skipped.** Their sites could not be researched. Set a research URL or remove them. **Sending is held and nothing goes out.** Check the three rows under the sequence editor: the brief, the research and the credits. **The opener sounds generic.** Sharpen the brief and the tone field, then review the summaries for the leads in question and edit any that are wrong. ## Related - [Merge tags and custom variables](https://docs.warmerly.com/help/merge-tags) - [How do I write an email sequence?](https://docs.warmerly.com/help/email-sequences) - [Campaign audience and the lead conversation view](https://docs.warmerly.com/help/campaign-audience) --- # How do I A/B test a subject line or email in a campaign? On the campaign's **Sequence** tab, open an email step and click **Test another version of this email**. You then have version A and version B side by side, and you can add up to four versions in total with **Add version C** and **Add version D**. Warmerly sends the versions in rotation, and once every version has had enough sends it picks a winner and uses only that one from then on. ## Steps 1. Open the campaign's **Sequence** tab and expand the email step you want to test. 2. Click **Test another version of this email**. 3. Edit each version's **subject** and **body**. Change one thing between versions (the subject, or one part of the body) so you can tell what made the difference. 4. Set **Decide after N sends each**. Every version must reach this number of sends before a winner can be chosen. Larger is more reliable and slower. 5. Launch, or keep the campaign running. Progress is shown under the versions. ## How versions are handed out Each new lead gets whichever version has been sent the least so far, so the split stays close to even across however many versions you have. While a test is running, the versions are the step's copy. What you typed in the step before enabling the test becomes version A. If you turn the test off, the winner (or version A if there is none yet) goes back into the step. ## How the winner is picked - Every version must have reached the **Decide after** number of sends. - The last email of each version must be at least 24 hours old, so recipients have had time to answer. - **Replies decide it.** As soon as any version has a reply, the highest reply rate wins. Only genuine replies count, not out-of-office auto-replies. - **Opens are the fallback.** If no version has a reply yet but some have opens, the highest open rate wins. Opens are only recorded when **Track opens** is on for the campaign, and they are unreliable, which is why replies come first. See [Open and click tracking](https://docs.warmerly.com/help/open-and-click-tracking). - If there are no replies and no opens at all, nothing is picked. Warmerly will not crown a winner with no evidence. When a winner is chosen, the step shows "Version X won" and every later send uses it. The losing versions can no longer be edited. Results per version (**Reply rate**, **Open rate** and a **Winner** badge) appear on the campaign's **Overview** tab under **Variant performance**. ## What it cannot do - The winner is simply the highest rate. It is not a statistical significance test, so a small sample can pick a version that is not really better. Use a sample size big enough to trust: a rate off a handful of sends is noise. - If you change both the subject and the body between versions, a winner tells you which email did better, not which change did it. The editor warns you about this, and warns if two versions are identical. ## Common problems **The test never picks a winner.** Check that every version has reached the sample size, that at least one reply exists (or that open tracking is on and at least one open exists), and that 24 hours have passed since the last send of each version. **Open tracking is off, so the test is slow.** Then replies decide it. That is the better signal, it just needs more sends to settle. **I need the copy in one place.** After a winner is chosen, turn the test off and the winner goes back to being the step's own copy. ## Related - [How do I write an email sequence?](https://docs.warmerly.com/help/email-sequences) - [What stops a campaign sequence for a lead?](https://docs.warmerly.com/help/what-stops-a-sequence) - [What the Warmi advice on a campaign means](https://docs.warmerly.com/help/campaign-advice) --- # How do I see who has been contacted in a campaign? Open the campaign and click the **Audience** tab. It lists every lead, how far each one has got through the sequence, and their status. Click the conversation icon on a row to open the **lead conversation**: the emails you sent, the lead's reply, and the emails still to come, written out with that lead's own details. ## The Audience tab The heading shows the number of leads. Above the table: - **Import leads** opens the file import. See [How do I import leads from a CSV?](https://docs.warmerly.com/help/import-leads-csv). - **Find leads** opens Warmerly's lead database with this campaign preselected, so leads you pick are added straight to it. - **Import from LinkedIn** brings leads in from LinkedIn. - **Find email (N)** appears when some LinkedIn leads have no email yet. It looks them up in the background. A lead whose lookup failed shows **Retry lookup**. - **Search** matches name, email or company. **Sort** offers Newest first, Oldest first and Name A to Z. - The **status filter** is a row of buttons with counts, campaign-wide and unaffected by your search: **All** and one for each status that has leads. Each row shows the lead, their company, their status, and a **Sent** column such as "2 of 3 sent" with a progress bar (it turns green once the lead replies), an open count if tracking is on, and how long ago the last email went out. Select rows with the checkboxes to **Remove** or **Export CSV** them. You can also remove one lead from its row. Removed leads stop receiving the remaining steps, and emails already sent are not affected. The empty state, "No leads yet", offers **Find leads** and **Import a file**. ## What each status means | Status | Meaning | |---|---| | Queued | Waiting to start. Nothing has been sent yet. | | Active | In progress through the sequence. | | Completed | Went through every step. | | Replied | They replied, and the campaign is set to stop on reply. | | Unavailable mailbox | The address bounced, or was already known to be dead. Sequence stopped. | | Unsubscribed | They unsubscribed, or were already on your do-not-contact list. | | Skipped | Not sent to, for example because the AI opener could not be written for them. | See [What stops a campaign sequence for a lead?](https://docs.warmerly.com/help/what-stops-a-sequence). The status counts also appear on the **Overview** tab under **Where your leads are**. On Overview, clicking **Total leads** or **Replies** jumps here with the matching filter. ## The lead conversation Click the conversation icon ("View the conversation") on a row. A panel opens with the lead's name, email and company, and then three kinds of entry: - **Sent and queued emails.** On the left, with their delivery marks (opened, clicked, bounced, or an error). - **Their reply.** On the right and tinted, so a reply stands out while you scroll. If the campaign stops on reply, a note says nothing further will send to them. - **Still to send.** Under the heading "Still to send", with a dashed border. These are the next email steps written out with this lead's own variables filled in, so you can see a blank before it goes out. Each has an **estimated** date. A collapsed section, "This lead's variables", lists the custom variables the lead carries. ### Things to know - **Replies are matched by the lead's address.** The panel shows mail from the lead's email address that arrived in your campaign's mailboxes, so it also catches replies sent from a phone or a new email. Warmup traffic is left out. - **The dates are estimates.** They count the step's wait and your campaign's sending days in the campaign's timezone. They do not model each mailbox's daily limit, the gap between sends, the ramp or recipient-local hours, so the real send can land some hours later inside the day. - **Only email steps are shown.** In a branching sequence, which arm a lead takes is not known in advance, so upcoming steps are not guessed. - **It never uses an AI credit.** An upcoming email using `{{ai_opener}}` is marked "written when this actually sends". - To answer a reply, use the [Inbox](https://docs.warmerly.com/help/inbox). ## Common problems **A lead's reply is missing from the conversation.** It may have come from an address that is not the one you emailed, or into a mailbox outside this campaign's project. **The Sent column says "Nothing sent".** The lead is still queued. See [Why does my campaign send fewer emails than my daily limit?](https://docs.warmerly.com/help/campaign-sending-schedule). **I cannot add more leads.** Your plan limits how many leads a campaign can hold. See [Plans and limits](https://docs.warmerly.com/plans-and-limits). ## Related - [Merge tags and custom variables](https://docs.warmerly.com/help/merge-tags) - [Campaign statuses](https://docs.warmerly.com/help/campaign-statuses) - [Campaigns API](https://docs.warmerly.com/campaigns) --- # What do the campaign statuses mean (draft, sending, paused, completed)? A new campaign is a **Draft** and sends nothing. When you start it, it goes live. While it is live, the campaigns list shows **Sending**, **Scheduled** or **Needs attention** depending on what it is doing. You can **Pause** it, and it becomes **Completed** by itself when no lead is left to contact. **Archived** campaigns are hidden from your main list. ## The statuses | Shown as | What it means | |---|---| | **Draft** | Created but never started. Nothing sends. The list's action reads "Add leads" if it has no leads, or "Finish setup" if it does. Drafts never count towards your active campaign limit. | | **Sending** | Live and working. Its Overview says "Sending." | | **Scheduled** | Live, but its next run is in the future, so it is waiting rather than sending right now. | | **Needs attention** | Live, but it has no sending account, or at least a fifth of its recent send attempts (over the last 7 days) failed. The list says which: "no sending account" or "failing to send". Action: **Add a sending account** or **Review failed sends**. | | **Paused** | Stopped by you. Nothing sends. Overview says "Paused, nothing is sending." Action: **Resume campaign**. | | **Completed** | Finished. Overview says "Finished." | | **Archived** | Moved out of your current list. Nothing sends. Action: **Restore campaign**. | "Live" is the active state. There is no separate "stalled" status. If a live campaign has not sent anything for two days or more, the [Warmi advice](https://docs.warmerly.com/help/campaign-advice) on the Overview tab says so and links to the Senders tab. Common causes are in [Why does my campaign send fewer emails than my daily limit?](https://docs.warmerly.com/help/campaign-sending-schedule) and [A campaign is not sending](https://docs.warmerly.com/troubleshooting#a-campaign-is-not-sending). A campaign whose only sender is your free mailbox will not send, because the free mailbox is for replies and tests. Add your own mailbox or a OneMail mailbox as a sender. See [How do I get a free sending mailbox?](https://docs.warmerly.com/help/free-sending-mailbox). ## The actions Buttons are at the top of the campaign page and in each row's actions menu on the **Campaigns** list. - **Start** (Draft). Runs the launch checks. Blockers stop it and each says how to fix it. Warnings show **Start anyway?** once, and you click **Start sending**. On success you see "Campaign started". See [What does the Warmi advice mean](https://docs.warmerly.com/help/campaign-advice) for the checks. - **Pause** (live). Confirms, then stops all sending for the campaign. Leads keep their places. Only a live campaign can be paused. - **Resume** (paused). Confirms, then sends again. It does not repeat the launch checks, but it is refused if your workspace is billing-locked or you have hit your monthly campaign send limit. - **Archive.** "It stops sending and moves out of your current campaigns. Nothing is deleted." Choose **Restore** in the same menu to bring it back. A restored campaign returns as a **Draft**, so it cannot start sending again without you pressing **Start**. - **Duplicate.** Makes a copy of the campaign. - **Delete permanently.** Deletes the campaign, its sequence, leads and sending history. It cannot be undone. Archive it instead if you might want it back. ## How a campaign becomes Completed After each pass, Warmerly checks whether any lead is still **Queued** or **Active**. When none is, the campaign is marked **Completed**. That means every lead has finished the sequence, replied, bounced, unsubscribed or been skipped. See [What stops a campaign sequence for a lead?](https://docs.warmerly.com/help/what-stops-a-sequence). ## Finding campaigns in the list The list hides Archived campaigns by default. The status filter lets you pick a single state, or show everything including Archived. The "Needs attention" section sits above the figures, because a campaign that cannot send matters more than a 30-day trend. ## Limits that involve status - **Active campaign limit.** Live and paused campaigns count towards your plan's limit of active campaigns. Drafts do not. If starting is refused because of the limit, archive one you no longer need or upgrade. See [Plans and limits](https://docs.warmerly.com/plans-and-limits). - **Billing lock.** If your workspace is locked for billing, campaigns do not send until it clears. ## Related - [How do I launch my first campaign?](https://docs.warmerly.com/help/launch-first-campaign) - [Campaign audience and the lead conversation view](https://docs.warmerly.com/help/campaign-audience) - [Campaigns API](https://docs.warmerly.com/campaigns) --- # Why does my campaign send fewer emails than my daily limit? Because the **daily limit** is only a ceiling, and something else usually stops the campaign first. The most common cause is the **minimum wait between sends** inside your sending hours. Next come the volume ramp on new mailboxes, each mailbox's own daily limit, and mailbox health. All of them are on the campaign's **Settings** tab except the mailbox limit, which is under **Accounts**. ## Where the settings are Open **Campaigns**, click the campaign, then the **Settings** tab. The relevant sections are **When it sends**, **How it sends** and, under **Advanced**, the ramp and recipient-local hours. **Save** at the bottom appears when you have changed something. ## The limits, in the order they bite **1. Sending days, hours and timezone (When it sends).** Nothing sends outside the days you tick (the default is Monday to Friday) and between the start and end hour (the default is 09:00 to 17:00) in the campaign's **Timezone**. The end hour has to be after the start hour. **2. Minimum wait between sends (How it sends).** This is the smallest gap between two emails from the same mailbox. The default is 10 minutes. Divide your sending window by the gap and you get the most one mailbox can send in a day: an 8-hour window with a 10-minute gap is about 48 per mailbox. Multiply by the number of mailboxes on the campaign for the campaign's real ceiling. If that number is lower than your daily limit, raising the daily limit changes nothing. Shorten the gap, widen the hours or add mailboxes instead. - Each mailbox also has its own minimum wait under **Accounts**. The longer of the two wins. - Warmup shares the same mailbox, so warmup sends also count against the gap. The real figure is a little lower than the arithmetic. - A very short gap looks machine-made to providers, so do not shrink it to zero for volume. **3. The daily limit (When it sends).** The most this campaign can send per day in total, spread across all its mailboxes. The default is 30. It accepts 1 to 50,000. **4. Each mailbox's own daily campaign limit (Accounts).** Every mailbox has a limit on campaign emails per day (30 by default). It is shared by every campaign that uses the mailbox, so two campaigns on one mailbox do not each get a full allowance. If you set the campaign's daily limit to 500 with two mailboxes at 30, you send at most 60. **5. The volume ramp (Advanced).** See the next section. **6. Mailbox health.** A mailbox with a rising bounce rate is slowed down, and a mailbox with a high one is taken off campaigns. See "Bounces slow a mailbox down" below. **7. Plan limits.** On the Free plan, campaign sends are metered monthly. See [Plans and limits](https://docs.warmerly.com/plans-and-limits). The free mailbox every account gets does not send campaigns; use your own connected mailbox or a OneMail mailbox. See [How do I get a free sending mailbox?](https://docs.warmerly.com/help/free-sending-mailbox). Warmi on the Overview and Settings tabs does this arithmetic for you. See [What the Warmi advice on a campaign means](https://docs.warmerly.com/help/campaign-advice). ## The volume ramp New mailboxes should not send at full volume on day one, so the ramp raises each mailbox's daily cap gradually. The starting figures are: - **Start at:** 3 emails per mailbox on the first sending day. - **Add per sending day:** 1. - **Up to:** 15 per mailbox per day. With those defaults a mailbox reaches full volume on its 13th sending day. How it works: - The ramp is **on by default** when you create a campaign in a project that has no mailbox yet, or that has any mailbox with fewer than 14 days of warmup. It is off by default if all your mailboxes are established, because a 15-a-day ceiling would hold a warm mailbox back below its own limit. - A "day" means a **sending day**. Weekends you do not send on do not advance it. - Pausing and resuming does not restart the ramp. - The ramp only ever tightens. It cannot push a mailbox past its own daily limit, so a ramp ceiling above the mailbox's limit stops at the mailbox limit. - Turn it off, or change the three numbers, under **Settings > Advanced > Ramp volume up gradually**. The panel previews the cap for days 1, 3, 5, 10 and 20. ## Recipient-local hours Under **Settings > Advanced > Recipient-local hours** you set the working hours (default 08:00 to 17:00) that apply in the lead's own timezone. This only works for leads whose country is known, such as leads pulled from Warmerly's lead database. Leads without a country, which is most CSV imports, fall back to your sending window above. Sending days are shared between the two. This never adds volume. It only decides what time of day a send is allowed, and every cap above still applies. ## Bounces slow a mailbox down Warmerly looks at each mailbox's bounce rate over the last 7 days, once it has at least 25 sends of history. Below 2% nothing changes. From 2% the mailbox's daily campaign cap is scaled down (to 75%, then 50%, then 25% as the rate climbs) and it never drops below 1 a day. At 7% the mailbox is taken off campaigns entirely, but **warmup keeps running** so it can rebuild its reputation. You get an email, the mailbox shows a **Recovering** badge, and it returns to campaigns by itself once its health score is back up, then ramps up gently for a few days. If a mailbox's mail is being refused as spam three times in a day, it is paused from campaigns the same way and the affected leads simply retry later. ## Several campaigns on the same mailboxes Campaigns take turns. The campaign that sent least recently goes first, so a busy campaign cannot starve a quieter one. It does not balance volume: a campaign with a high daily limit still sends more than one with a low limit. ## Common problems **Active, but nothing has sent for days.** Usually the audience has run out, every mailbox is at its cap for the day, or the sending window has not opened in the campaign's timezone. Check the Overview tab and the Senders tab. Work through [A campaign is not sending](https://docs.warmerly.com/troubleshooting#a-campaign-is-not-sending). **I raised the daily limit and nothing changed.** The gap between sends is the ceiling. Read point 2 above. **Day one sent only 3 emails per mailbox.** That is the ramp for a new mailbox, working as intended. ## Related - [How warmup works](https://docs.warmerly.com/how-warmup-works) - [How do I launch my first campaign?](https://docs.warmerly.com/help/launch-first-campaign) - [What is a campaign's status?](https://docs.warmerly.com/help/campaign-statuses) --- # Can I launch a campaign before my mailbox has finished warming up? Yes, you can build your sequence and launch on the day you sign up. You do not have to come back later. Warmerly keeps the early sending gentle for you. What you get depends on which mailbox the campaign uses. ## If you use your free mailbox Every account has one free mailbox that starts warming up at signup. It warms up and can be used for replies and tests, but it does not send campaigns. To send a campaign, connect your own mailbox (Google, Microsoft or SMTP) or add a hosted OneMail mailbox, which sends to verified addresses. See [How do I get a free sending mailbox?](https://docs.warmerly.com/help/free-sending-mailbox). If the free mailbox is the only sender on a campaign, the launch check tells you so and names what to connect. ## If you use your own connected mailbox A mailbox you have connected can be used in a campaign straight away. To keep a young mailbox safe, the campaign's **volume ramp** is switched on automatically when you create it if your project has no mailbox yet, or any mailbox has fewer than 14 days of warmup: - **Day one: 3 emails per mailbox.** - Then 1 more per sending day, up to 15 per mailbox per day (about the 13th sending day). - Sending days only count, so weekends you do not send on do not advance it. You can change or switch off the ramp under the campaign's **Settings > Advanced**. For a project where every mailbox is already established, the ramp starts off, so it does not hold a warm mailbox back. Details are in [Why does my campaign send fewer emails than my daily limit?](https://docs.warmerly.com/help/campaign-sending-schedule). Keep **warmup switched on** while you send. It keeps running alongside your campaigns and is what builds the reputation that lets volume grow. See [How warmup works](https://docs.warmerly.com/how-warmup-works). ## What day one looks like - The campaign is **live** from the moment you start it. - Nothing is sent outside your sending days and hours. - A new mailbox sends only a few emails a day at first, so the campaign will look slow. That is the ramp working, not a fault. ## What this does not do - It does not make a brand-new domain safe to blast. The ramp limits day-one volume; it does not replace warmup or correct DNS. Check your mailbox's DKIM, SPF and DMARC. See the [guides](https://docs.warmerly.com/guides). - It does not make the free mailbox send campaigns. - It does not skip your plan's limits. See [Plans and limits](https://docs.warmerly.com/plans-and-limits). ## Common problems **The launch check says the free mailbox cannot send campaigns.** Connect your own mailbox or add a OneMail mailbox on **Accounts**, then try again. **The launch check says something else.** Read the reason. Fix the mailbox on **Accounts**, then try again. **Launched, but nothing has sent.** Check the date in **Launch readiness**, your sending days and hours, and the [troubleshooting checklist](https://docs.warmerly.com/troubleshooting#a-campaign-is-not-sending). ## Related - [How do I launch my first campaign?](https://docs.warmerly.com/help/launch-first-campaign) - [How do I get a free sending mailbox?](https://docs.warmerly.com/help/free-sending-mailbox) - [Campaign statuses](https://docs.warmerly.com/help/campaign-statuses) --- # What stops a campaign sequence for a lead? A lead's sequence stops when they reply, when their address bounces, when they unsubscribe, when their address is on your do-not-contact list, when you remove them, or when they finish the last step. Each one gives the lead a status you can see on the campaign's **Audience** tab. Two of them, **Stop on reply** and **Stop on auto-reply**, are switches you control in the campaign's **Settings** tab. ## Replies Under **Settings > How it sends** there are two switches, both on by default: - **Stop on reply.** "Halt the sequence for a lead as soon as they reply." The lead's status becomes **Replied** and nothing further is sent to them. - **Stop on auto-reply.** "Treat out-of-office replies as a stop signal." With it on, an automatic reply stops the sequence like a real one. With it off, the auto-reply is noted on the email but the lead keeps receiving their steps. If you turn **Stop on reply** off, a real reply no longer stops the sequence, so the lead keeps getting the next emails. Leave it on unless you have a reason. Things to know: - Warmerly finds replies by reading the connected mailbox that sent the email, which it checks every few minutes, and matching the reply to the email it answers. A reply can be missed if it arrives without the reply headers (some forwards, or a brand-new email the person wrote from scratch). If a lead has clearly answered but is still in the sequence, remove them on the Audience tab. - Replies show up in your [Inbox](https://docs.warmerly.com/help/inbox). Open the lead's conversation on the Audience tab to see the sent emails and their reply together. - Real replies are also what an [A/B test](https://docs.warmerly.com/help/ab-test-email-copy) counts. Auto-replies are not counted. ## Bounces If a sent email comes back undeliverable (a "mailer-daemon" or "delivery failed" message, or a permanent rejection of the address), the lead's status becomes **Unavailable mailbox**, the sequence stops, and the address is added to a do-not-contact list so no campaign emails it again. The label is deliberately neutral. A lead can show **Unavailable mailbox** even though your own email never bounced, because the address was already known to be dead from a bounce elsewhere, and Warmerly skips it to protect your sender reputation. Warmerly separates a dead address from a rejected message. If a provider refuses your mail as spam rather than because the address is bad, the lead is not marked as bounced or suppressed. It retries later, and after repeated refusals the mailbox is taken off campaigns while it recovers. See [Why does my campaign send fewer emails than my daily limit?](https://docs.warmerly.com/help/campaign-sending-schedule). A high bounce rate damages your domain. Verify lists before importing them, using **Prospecting > Email verification** in the sidebar (developers: the [Verify API](https://docs.warmerly.com/verify)). ## Unsubscribes Every campaign email carries an unsubscribe link and the one-click unsubscribe headers that Gmail and Yahoo require. When a lead uses either, their status becomes **Unsubscribed**, the sequence stops immediately, and the address goes on your workspace's do-not-contact list, so no campaign in that workspace emails them again. See [Unsubscribe links](https://docs.warmerly.com/help/unsubscribe-links). ## The do-not-contact list Right before each email is sent, Warmerly checks the recipient against the do-not-contact lists. A suppressed address is never emailed, in any campaign in that workspace. The lead is marked **Unsubscribed** or **Unavailable mailbox** depending on why the address is listed. Add addresses yourself under **Settings > Do not contact** (paste one per line or separated by commas, then **Add to do-not-contact**). It takes effect straight away, which is what you want when someone tells you to stop on a call. Limits to be aware of: the page is add-only. It does not show you the list and you cannot remove an address from it yourself. If you removed one by mistake, contact support through Warmi in the app. There is more in the [Suppression API](https://docs.warmerly.com/suppression). ## Skipped A lead can show **Skipped**. The usual reasons are that the step uses `{{ai_opener}}` and Warmerly could not research the lead's website, or that the recipient's server permanently rejected the message in a way that does not prove the address is dead. Skipped leads are not sent to further. See [AI personalisation](https://docs.warmerly.com/help/ai-opener). ## You remove them or they finish - **Remove** on the Audience tab (one lead, or several with the checkboxes) takes leads out of the campaign. They stop receiving the remaining steps. Emails already sent are not affected. - A lead that reaches the end of the sequence becomes **Completed**. - When no lead is left queued or in progress, the whole campaign becomes **Completed**. See [Campaign statuses](https://docs.warmerly.com/help/campaign-statuses). ## Pausing is different Pausing a campaign stops all sending for every lead until you resume, but no lead's status changes. A paused mailbox stops sending too. Pausing does not free up a step you want to delete, because leads are still sitting on it. ## Related - [Campaign audience and the lead conversation view](https://docs.warmerly.com/help/campaign-audience) - [Open and click tracking](https://docs.warmerly.com/help/open-and-click-tracking) - [Troubleshooting](https://docs.warmerly.com/troubleshooting) --- # How do open and click tracking work in a campaign? Open the campaign, go to **Settings** and find the **Tracking** section. It has three switches: **Send as plain text only**, **Track opens** and **Track clicks**. For a new campaign, **Track clicks** is on, **Track opens** is off and plain text is off. The section only appears on campaigns that send email. ## What each switch does **Track clicks.** "See when a lead clicks a link in your email." Warmerly rewrites each link so it goes through a tracking address first, records the click, then sends the person on to your real page. The recipient sees a slightly different link if they hover over it. **Track opens.** "See when a lead opens your email." Warmerly adds a tiny invisible image to the email. When the recipient's email app loads the image, the open is recorded. Some email apps block images or load them automatically, so open numbers are a rough guide, not a count of people. That is why open tracking is off by default. The hidden image is also one of the more reliable signs of bulk email to spam filters. **Send as plain text only.** Removes the HTML version of the email entirely. There is no tracking image, no rewritten links and no formatted signature (the signature is HTML). This is usually the biggest single improvement to inbox placement for cold outreach, at the cost of open and click tracking. While it is on, the two tracking switches are greyed out and record nothing. Both tracking switches are per campaign. Existing campaigns keep the values they were saved with. ## Where the numbers appear - **Overview tab > What your emails did:** Sent, Opened, Clicked, Replied, Bounced and Failed, each as a share of sent emails. Opened and Clicked stay at zero if tracking is off. - **Audience tab:** the Sent column shows an open count per lead next to how many steps have been sent. - **The lead conversation view:** each email carries its own delivery marks (opened, clicked, bounced or an error). Bounced means the recipient's server rejected the email, often a bad or full inbox. Failed means the email never left, usually a sending problem. There is no separate "delivered" figure. ## What the numbers do not tell you - An open can be recorded when nobody looked at the email, and a missed open is common when images are blocked. - Some companies run security software that opens every link in incoming mail. That can record clicks that no human made. - Replies are the number to trust. That is why an [A/B test](https://docs.warmerly.com/help/ab-test-email-copy) is decided on replies first and uses opens only as a fallback. ## Tracking that leads to a branch or an A/B test A **Condition** step that branches on "opened" or "clicked" only fires if the open or click was recorded, so it needs the matching switch on. See [How do I write an email sequence?](https://docs.warmerly.com/help/email-sequences). ## Custom tracking domain Open and click tracking only works on a mailbox that has a **custom tracking domain**: your own domain (for example `track.yourdomain.com`) that carries the tracked links. It looks more trustworthy and keeps your link reputation separate from other senders. A mailbox without one sends with no tracking at all (no pixel, no wrapped links), and with no unsubscribe link either (see below). You set it per mailbox: **Accounts > the mailbox > Settings > Custom tracking domain**. You add one CNAME record at your domain host. Warmerly verifies the record, then checks that HTTPS works for your domain with a valid certificate. Warmerly does not issue that certificate, so your domain must sit behind a service that does (for example Cloudflare with the proxy on). The full walkthrough is in [How do I use a custom tracking domain?](https://docs.warmerly.com/guides/custom-tracking-domain). Two behaviours to know: - A domain that is **not yet verified, or has no working HTTPS, is not used**. The mailbox sends with no tracking and no unsubscribe link until both checks pass, so a half-finished setup never produces broken or certificate-error links. - If a mailbox has no working tracking domain, the launch check and the email preview say so. It is a warning, not a block: you can launch, and you are then responsible for including your own way to opt out. The unsubscribe link in your emails is never rewritten as a tracked link. It lives on your custom tracking domain when you have a working one, and is left out when you do not. See [Unsubscribe links](https://docs.warmerly.com/help/unsubscribe-links). ## Common problems **Opens stay at zero.** Open tracking is off (the default), plain text mode is on, or the recipients' apps block images. Turn on **Track opens** and turn off plain text if you need open numbers, knowing the tradeoff. **Clicks are recorded but nobody replied.** Link scanners can click for the recipient. Judge by replies. **Warmi says tracking will record nothing.** That message on the Settings tab means plain text is on together with a tracking switch. Turn one of them off. ## Related - [How do I use a custom tracking domain?](https://docs.warmerly.com/guides/custom-tracking-domain) - [What the Warmi advice on a campaign means](https://docs.warmerly.com/help/campaign-advice) - [How do I set up SPF and DMARC?](https://docs.warmerly.com/guides/spf-dmarc) --- # How do unsubscribe links work in campaign emails? When a mailbox has a [verified custom tracking domain](https://docs.warmerly.com/guides/custom-tracking-domain) with working HTTPS, you do not add an unsubscribe link yourself. Warmerly adds one to the footer of every campaign email from that mailbox, and adds the one-click unsubscribe headers that Gmail and Yahoo look for. When a lead unsubscribes, their sequence stops at once and they are never emailed again by any campaign in your workspace. **Without a working tracking domain, Warmerly adds no unsubscribe link.** That mailbox sends in what we call no-link mode: no unsubscribe link, no one-click headers, no open or click tracking, and nothing of ours in the email. You are then responsible for including a way to opt out in your own wording, as the law where you and your recipients are requires. Replies are not treated as unsubscribes, so add any address that opts out under **Settings > Do not contact** yourself. The launch check and the email preview both tell you when a mailbox is in this mode. ## What the footer contains Below your message and signature, Warmerly adds a footer with: 1. A thin divider. 2. A **sender identity line**: your business name and postal address, if you have set them. 3. The word **Unsubscribe**, as a link. It is deliberately easy to see, because a recipient who cannot find it clicks "report spam" instead, which hurts your domain far more. The footer goes into both the HTML and the plain-text version of the email, so it is there even when a campaign is set to **Send as plain text only**. The unsubscribe link is never turned into a tracked link. On the **Free** plan, one more small line, "Sent with Warmerly", sits under the unsubscribe link. Paid plans do not have it. See [Plans and limits](https://docs.warmerly.com/plans-and-limits). There is no setting to remove or reword the unsubscribe link. To see exactly what a lead will get, click **Preview** on an email step: it shows the same footer, including the "Sent with Warmerly" line on Free and no identity line if you have not set one. ## Add your business name and address Anti-spam laws (CAN-SPAM in the US, CASL in Canada, and similar rules elsewhere) ask for a real postal address in commercial email. It is your address that matters, not Warmerly's. Also check your local rules, for example Canada's CASL and Australia's Spam Act. 1. Open **Settings > Team**. 2. Find **Sender details**. 3. Fill in **Business name** and **Postal address**, then save. These are optional and apply to every campaign in the workspace. Campaigns send with or without them. If you leave the address empty, the footer just omits it (and shows the business name or sender name alone if you set one), and the campaign's **Launch readiness** list shows a warning with a **Fix in Settings** link. You can accept the warning and launch. Only people who can manage the workspace see the editable fields. ## What happens when a lead unsubscribes - Clicking the link, or using the "Unsubscribe" button that Gmail and Yahoo show, marks the lead **Unsubscribed** on the campaign's Audience tab. - The sequence stops. Any step still due is not sent. - The address is added to your workspace's do-not-contact list, so it is skipped by every other campaign too. You do not need to do anything. - The person sees a short page confirming they will get no more emails from this sender's campaign. If the link fails for some reason, the page offers a form: "type the address this email was sent to". Typing the matching address unsubscribes them. This exists so nobody is left with no way out, since a frustrated recipient marks you as spam instead. ## Someone asks you to stop by reply or phone You do not need the link. Add them under **Settings > Do not contact**, one address per line. It takes effect immediately. See [What stops a campaign sequence for a lead?](https://docs.warmerly.com/help/what-stops-a-sequence). A reply also stops the lead's sequence by default (the **Stop on reply** switch). ## Where the link points The unsubscribe link and its headers use your own [custom tracking domain](https://docs.warmerly.com/guides/custom-tracking-domain), the same one as your tracked links, once it is verified and HTTPS works for it. If Warmerly has set up a shared link address for its customers, a mailbox without a tracking domain uses that. Otherwise there is no link (see above). Warmerly's own website is never used. A tracking domain of your own is the way to get one-click unsubscribe, and it is better for deliverability. ## Common problems **A lead shows Unsubscribed but never asked.** Some companies run security software that opens every link in an email. If it opens the unsubscribe link, the lead is unsubscribed. Nothing is sent to them afterwards, and you can contact them by another route if you know they are interested. **I want to email someone who unsubscribed.** Not possible from Warmerly. The do-not-contact list is add-only for customers: you cannot see or remove entries. **The footer shows no address.** You have not filled in **Sender details** yet. ## Related - [What stops a campaign sequence for a lead?](https://docs.warmerly.com/help/what-stops-a-sequence) - [Open and click tracking](https://docs.warmerly.com/help/open-and-click-tracking) - [Suppression API](https://docs.warmerly.com/suppression) --- # What does the Warmi advice on my campaign mean? A campaign shows a card with Warmi, the assistant, when it has spotted something worth your attention. On the **Overview** tab it reads "Warmi looked at this campaign" and looks at your results. On the **Settings** tab it reads "Warmi checked these settings" and looks at whether your settings agree with each other. Each line is a short observation, usually with a button that takes you to the fix. The advice is only a suggestion. It never stops you saving a setting and never stops a launch. The **Launch readiness** list (below) is what checks a campaign before it starts. ## How the card behaves - **No card means nothing to say.** Warmi does not show a "everything looks fine" panel. - Lines are ordered warnings first, then information, then good news, and only the top few are shown. - Many lines have a question you can click. It opens the Warmi chat with the question already asked, so you can get the reasoning and a suggested value. - The Settings card reads your unsaved changes too, so you see the effect of an edit before you save it. ## Advice on the Overview tab (your results) | What Warmi says | What it means and what to do | |---|---| | A bounce rate of 3% or more (once at least 50 emails are sent) | Providers start filtering a domain above about 3% bounces. Pause, then verify the rest of the list before sending more. The link goes to the Audience tab. | | Active, but nothing has sent in two days or more | Usually the audience has run out, every mailbox is at its cap, or the sending window has not opened. The link goes to the Senders tab. See [Why does my campaign send fewer emails than my daily limit?](https://docs.warmerly.com/help/campaign-sending-schedule). | | A reply rate under 0.5% after 200 or more sends | At that volume it is the copy or the list, not luck. Try a second version of the first email. See [A/B testing](https://docs.warmerly.com/help/ab-test-email-copy). | | Everyone has been contacted | No lead is waiting. Add leads to keep it running. | | A reply rate of 3% or more after 100 or more sends | Good. Add leads instead of rewriting anything. | ## Advice on the Settings tab (do these settings agree?) | What Warmi says | What it means and what to do | |---|---| | No mailboxes are attached | Nothing can send. Add mailboxes on the Senders tab. | | The daily limit is higher than the gap between sends allows | The minimum wait between sends, inside your sending hours, is the real ceiling, and raising the limit changes nothing. Shorten the gap, widen the hours or add mailboxes. The card states the number your settings top out at. | | No sending days are selected | The campaign will never send. Pick days. | | Plain text is on together with open or click tracking | Plain text removes the tracking, so nothing will be recorded. Turn one off. See [Open and click tracking](https://docs.warmerly.com/help/open-and-click-tracking). | | An A/B test is running with open tracking off | Replies will decide the winner. That is the better signal, it just needs more sends. | | The ramp climbs higher than your sending gap allows | The ramp will finish climbing into a ceiling it cannot reach. Review it under Advanced. | The daily-limit number is an upper bound. Warmup shares the same mailbox and is not counted in it, so the real figure is a little lower. ## The Launch readiness list On the **Overview** tab of a campaign that has not started (and kept below the results afterwards), **Launch readiness** lists what would stop it or make it worse. Each row that needs attention has a **Fix in ...** link that goes to the tab where you fix it. There are two kinds of row: - **Blockers** must be fixed before the campaign starts: no email step with content, no sending mailbox, no leads waiting, a merge tag that exists on none of your leads, the `{{ai_opener}}` tag used with no personalization brief, a plan that does not include a channel you use or a monthly send limit reached, or the AI service not answering when you press Start. - **Warnings** can be accepted. You see **Start anyway?** once, click **Start sending**, and it goes ahead: no postal address set in Settings, mailbox DNS not passing, more than five mailboxes on one domain, tracking on with no verified tracking domain, or more than a fifth of leads missing the website research the opener wants. If the campaign is paused, the list reminds you that everything is ready but you need to click **Resume**. ## Common problems **Warmi's card disappeared.** It only shows when there is something to say. A healthy campaign shows nothing. **Warmi says my daily limit cannot be reached.** Read the Settings card's number. It is about the gap between sends, not about the limit. **Warmi flagged bounces, but I want to keep sending.** You can, but a rate above about 3% harms every mailbox on the campaign, and mailboxes over higher rates are slowed and then taken off campaigns automatically. Verify the list first. ## Related - [Why does my campaign send fewer emails than my daily limit?](https://docs.warmerly.com/help/campaign-sending-schedule) - [How do I launch my first campaign?](https://docs.warmerly.com/help/launch-first-campaign) - [Campaign statuses](https://docs.warmerly.com/help/campaign-statuses) --- # How does the Inbox work? (replies, categories and answering leads) Open **Inbox** in the sidebar (under **Outreach**). It gathers the mail from every mailbox in your workspace, and your LinkedIn and WhatsApp conversations, into one list of conversations with the newest first. Replies to your campaigns are sorted for you, and you can answer without leaving the page. The default view is **Needs reply**. ## Views, search and filters Along the top: - **Search all mail** matches a contact's name, email, phone or company, and the words in their messages. Partial words work, so "invo" finds "invoice". - **Needs reply** shows conversations whose newest message is from them and that are classed as a lead. **All** shows every conversation. The count on the right reads "N conversations". - **Filters** opens a small panel: **Project** and **Account** (only shown if you have more than one), **Channel** (All, Email, LinkedIn, WhatsApp), **Category** (All, Interested, Not relevant, Spam) and **Unread only**. A number on the button shows how many filters are on, and **Clear** removes them. Above the list, the **Refresh** button fetches new mail now, and the three-dot **Inbox actions** menu has **Select conversations**, **Mark N listed read** and **View archived**. A bar reading "New activity, refresh list" appears when something arrives while you are looking. Archive a conversation with the archive icon on its row (or select several and choose **Archive selected**). Archived conversations are under **View archived**, where the same button reads **Unarchive**. ## Which mail appears - **Warmup mail is never shown.** It is filtered out of every view. - **Automatic senders are hidden** too: mailer-daemon, postmaster, no-reply and notifications addresses, and LinkedIn notification emails. - New mail is read from your mailboxes roughly every five minutes. Use **Refresh** if you cannot wait. See [Replies are not showing in the inbox](https://docs.warmerly.com/troubleshooting#replies-are-not-showing-in-the-inbox). - Both the Inbox and Sent folders are read, so mail you send from your own email app appears too. Emails sent by campaigns and warmup are not copied into a mailbox's Sent folder, so they do not appear in other email apps. Emails you send from Warmerly's own Inbox do show in the conversation. - A mailbox that needs reconnecting stops syncing. See [Why did my mailbox disconnect?](https://docs.warmerly.com/help/reconnect-mailbox). ## Categories Each conversation shows a small badge. Click it to change it: **Mark as Lead**, **Mark as Not Relevant** or **Mark as Spam**. Your choice moves the conversation into or out of **Needs reply** straight away, and it is kept. | Badge | Filter name | Meaning | |---|---|---| | Lead (the list row says **Interested**) | Interested | A real person replying with interest, a question or engagement about your outreach | | Not Relevant | Not relevant | Out-of-office and auto-replies, receipts and confirmations, or unrelated replies | | Spam | Spam | Mail in the mailbox's spam folder | | Unclassified | none | Not graded | How a category is chosen: 1. Simple rules first: the spam folder, bounce and mailer-daemon mail, mail carrying an unsubscribe header, out-of-office subjects, and Warmerly's own emails to you. 2. An AI check next, but **only for people who are leads in one of your campaigns**. This keeps a newly connected mailbox from grading years of ordinary correspondence. 3. Anything else stays **Unclassified**. It still shows under **All**, but it is not in **Needs reply** until you mark it as a Lead. A reply that arrives from a different address than the one you emailed is not graded by the AI. Mark it yourself if it matters. Each conversation may also show the name of the campaign it came from. ## Replying Click a conversation to read the thread, then write in the box at the bottom. 1. Choose **Reply via Email, LinkedIn or WhatsApp** if this person has more than one channel. 2. For email, replies always send from the mailbox the thread started with. Its address is shown in the corner. You cannot pick another for that thread. 3. Click **Edit subject** if you want to change the subject. 4. Write your reply and click **Send** (or press Ctrl+Enter, or Command+Enter on a Mac). Your mailbox signature and the quoted message are added for you. Common send errors are shown in plain words, for example that the WhatsApp account is disconnected, the contact has no email address or the subject is missing. **Draft with AI** (or **Rewrite with AI** if you have already typed something) appears on conversations classed as a lead. It writes a short, plain-text reply of under 120 words in your name. Read it and edit it before you send. The conversation may already have an autosaved draft waiting when you open it. If a draft cannot be generated, try again in a moment. To start a new conversation, click **Compose** at the top right, choose the account to send **From**, and fill in **To**, **Subject** and **Message** (Cc is available). Images in received emails are blocked, so the sender cannot tell you opened it. ## Being told about new leads When the AI classes new replies as leads, you get an email, "You have new leads to reply to", with a button to open the Inbox. At most one such email is sent in 24 hours, and it lists the leads found since the last one. You can switch these emails off with the link in the email or under **Settings > Email preferences**. ## What the Inbox cannot do - It does not show warmup traffic, ever. - It does not grade mail from people who are not in your campaigns, so unrelated correspondence is Unclassified. - You cannot change the sending mailbox on an existing thread. - A campaign lead's status changes when their reply is detected arriving, not when you answer. That is what stops the sequence, if **Stop on reply** is on. See [What stops a campaign sequence for a lead?](https://docs.warmerly.com/help/what-stops-a-sequence). ## Common problems **A reply I expect is not here.** Check the mailbox is connected, click **Refresh**, and check the view and filters. Under **Needs reply** you only see conversations classed as a lead. Switch to **All**. **A reply is in the wrong category.** Click its badge and change it. **I cannot send.** Read the message under the reply box. The usual causes are a disconnected account or a missing subject. ## Related - [Campaign audience and the lead conversation view](https://docs.warmerly.com/help/campaign-audience) - [Inbox API](https://docs.warmerly.com/inbox) - [Troubleshooting](https://docs.warmerly.com/troubleshooting) --- # What do my mailbox's health score and status mean? Every mailbox has a **health score** from 0 to 100 and a **status badge** on **Accounts**. The score says how well its warmup mail is landing. The badge says whether the mailbox is working, and that is not always the same thing as the score. Open a mailbox from **Accounts** to see both, along with its checks and charts. ## Where to look Click a mailbox on **Accounts**. The page has four tabs: - **Overview**: the warmup banner, the tiles (deliverability health, inbox placement, emails sent today, spam rate), the performance charts and Warmi's notes. - **Health**: the [domain health card](https://docs.warmerly.com/help/domain-health-card) and [inbox placement](https://docs.warmerly.com/help/placement-tests). - **Warmup**: the on/off control, the daily volume explanation, the ramp and a forecast. - **Settings**: sender name and signature, daily sending limit, tracking domain and DKIM selector. The buttons at the top of the page are **Pause** or **Resume**, and **Reconnect** when the mailbox cannot sign in. ## The status badges | Badge | What it means | What to do | | --- | --- | --- | | **Healthy** | Connected, and the health score is 70 or above | Nothing | | **Warming** | Still in its first two weeks, or not scored yet | Let warmup run. A low score in the first 14 days is expected | | **Paused** | Stopped, either by you or automatically | See [why a mailbox is paused](#my-mailbox-is-paused) | | **Recovering** | Taken off campaigns for reputation, warmup still running | Warmup keeps running and campaign sending returns automatically once the mailbox is healthy again; if your whole workspace was restricted, our team may also take a look. Cleaning your list gets it there faster. See [sending slowed or paused](https://docs.warmerly.com/help/sending-slowed-or-paused) | | **Needs attention** or **At risk** | Connected, but the score is below 70 after the first two weeks | Read the checks on the Overview tab and run a [placement test](https://docs.warmerly.com/help/placement-tests) | | **Disconnected** | Warmerly cannot sign in | [Reconnect it](https://docs.warmerly.com/help/reconnect-mailbox) | A badge only says what Warmerly can see. A mailbox with no health score yet shows **Warming**, not a green tick, because nothing has been measured. ## How the health score is worked out The score is recalculated once a day from the last 7 days of warmup mail sent from that mailbox. It blends four things: | Signal | Weight | | --- | --- | | Share of warmup mail that reached the inbox instead of spam | About half | | Few rejected messages (bounces) | One fifth | | Replies received to warmup mail | 15% | | Share of warmup mail that was delivered and found by the receiving mailbox | 15% | The score is not a promise about your cold email. It measures warmup traffic inside the warmup network. To see how a real message from your mailbox is treated, run a [placement test](https://docs.warmerly.com/help/placement-tests). See also [How warmup works](https://docs.warmerly.com/how-warmup-works) for the difference between the warmup reply rate and a campaign reply rate. **No score yet.** The first score appears after a day or so of warmup, once some warmup mail has been delivered and classified. A new mailbox showing dashes is normal. **"Not scored since ..."** means scoring stopped producing new results for this mailbox, so the number shown is old. Check that the mailbox is connected and that warmup is on. If Warmerly sends a lot of warmup mail from a mailbox and cannot tell where any of it landed, you will also get an alert about it. ## The checks on the Overview tab - **Steady sending pattern**: whether warmup mail went out on most of the last 7 days. - **Landing in the inbox**: the share of scored warmup mail that reached the inbox. Shown only once there is data. - **Low spam rate**: the share that went to spam. - **Positive engagement**: whether warmup mail is getting replies. - **Building reputation**: whether the score is rising or holding at a healthy level. Each shows good, watch or unknown. **Unknown** means there is not enough data yet. It is never a hidden pass. ## My mailbox is paused There are three different reasons, and they behave differently: 1. **You paused it** with the **Pause** button. Click **Resume** when ready. The warmup ramp carries on from where it stopped. 2. **Warmerly paused it because it could not sign in.** The mailbox shows **Disconnected** and a **Reconnect** button. Warmup and campaign sending both stop until it is fixed. If the cause was only that the mail server was unreachable, Warmerly retries on its own about every 30 minutes. A wrong password is never retried. See [Why did my mailbox disconnect?](https://docs.warmerly.com/help/reconnect-mailbox). 3. **Warmerly paused it for a low score.** If the health score stays under 60 for two days in a row, the mailbox is paused. It is resumed automatically after a cooldown of about three days, unless you paused it yourself in the meantime. A mailbox that is **Recovering** is a different case again: it is off campaigns only, and warmup keeps running. See [Why did sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused). ## Warmup off is not the same as paused Turning warmup off on the **Warmup** tab stops the warmup mail but leaves the mailbox able to send campaigns. The banner then says warmup is turned off and that the mailbox's reputation is not being built or maintained. That is allowed, but it is rarely a good idea for a mailbox you send cold email from. The free mailbox that comes with every account cannot be paused or have warmup turned off. ## Common problems **The score is low on day three.** Expected. A brand-new mailbox is not judged as struggling until it is past its first two weeks. **Healthy badge, but campaigns are not sending.** The badge describes health, not campaign status. Check the campaign itself and the [troubleshooting list](https://docs.warmerly.com/troubleshooting#a-campaign-is-not-sending). **Score dropped suddenly.** Look at the domain health card for a failed DNS record or a blocklist listing, then run a placement test. See the [deliverability checklist](https://docs.warmerly.com/guides/deliverability-checklist). ## Related - [How warmup works](https://docs.warmerly.com/how-warmup-works) - [Why did sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused) - [Domain health card](https://docs.warmerly.com/help/domain-health-card) - [Warmup API](https://docs.warmerly.com/warmup) for the same data over HTTP --- # How do I read the domain health card? The domain health card checks the DNS records and blocklists that decide whether mailbox providers trust mail from your domain. Open it from **Accounts**, click a mailbox, then open the **Health** tab. Each check shows one of four states, and the card's headline is the worst of them. ## The four states | State | Meaning | | --- | --- | | **Pass** | Checked and fine | | **Warn** | Works, but there is something worth tightening. Not a failure | | **Fail** | Something is missing or broken and it will hurt delivery | | **Unknown** | Warmerly could not get an answer this time. This is not a pass and not a fail | **Unknown is never shown as green.** If a DNS server was slow or a blocklist refused the query, the check says so and tries again automatically. Do not change your DNS because of an unknown result. ## What is checked ### SPF Which servers may send as your domain. The card flags: - **No SPF record** (fail). - **More than one SPF record**, or a record with an unreadable part (fail). Providers ignore a broken SPF record completely. - **SPF authorises the entire internet** (fail), meaning a record ending in `+all`. - **Too many DNS lookups** (fail when over the limit of 10, warn when close to it). - **No ending rule**, or an ending that takes no position on unknown senders (warn). - **Soft fail** (`~all`) is shown as information only and does not lower the state. ### DKIM Whether your mail is signed. The card flags **No DKIM signature found** (fail), **DKIM is still in test mode** (warn) and **a short key** (warn). Warmerly finds DKIM by trying a list of common selector names. If your provider uses an unusual one, the card can say "none" for a domain that is signed. Enter your selector under **Settings, DKIM selector** and re-check. See [Setting up DKIM](https://docs.warmerly.com/guides/dkim) and [Troubleshooting](https://docs.warmerly.com/troubleshooting#dkim-shows-missing-but-the-record-exists). ### DMARC The policy telling receivers what to do with forged mail. The card flags **No DMARC record** (fail), **DMARC is monitor-only** (warn, and very common, since `p=none` is the normal starting point) and a record with no policy (warn). Applying to only part of your mail, or not collecting reports, are shown as information. See [SPF & DMARC](https://docs.warmerly.com/guides/spf-dmarc). ### MX Whether your domain can receive mail. **No MX records** is a fail: a domain that cannot receive replies looks suspicious, and warmup needs replies. ### Blocklists Your domain and your mail server's IP address are checked against public spam blocklists. Warmerly checks six domain lists and ten IP lists. See [What if my domain or IP is on a blocklist?](https://docs.warmerly.com/help/blocklisted) for how to read a listing and get removed. Blocklist results can be: - **Clean on all N lists**: pass. - **Clean on some lists, others did not answer**: warn, and the card says how many did not answer. It is honest that the picture is incomplete. - **Your domain is blocklisted** or **Your mail server's IP is blocklisted**: fail. - **This IP range isn't meant for sending**: warn. This is a statement about the IP range (typically a home or office connection), not a spam report against you. - **Blocklist status unknown**: unknown. ## "Your mail server's IP" is not always yours The IP check looks up the mail server your mailbox submits mail to. For a small or self-hosted mail server, that is the address your mail leaves from. For large providers such as Gmail or Microsoft 365, your mail leaves from a different pool, so Warmerly skips the IP check for them and says so, rather than reporting on an address you cannot control. ## Gmail, Outlook and other shared domains If your mailbox address is on gmail.com, outlook.com or a similar consumer domain, the DNS records belong to the provider. The card shows a headline like "You're all set, gmail.com is managed by Gmail" instead of grading records you cannot change, and the domain itself is not checked against blocklists. ## Re-checking Click **Re-check now** after you change a DNS record. DNS records are re-read immediately. Blocklists are checked at most about every six hours, so a re-check may reuse a recent blocklist result. DNS records are also re-checked automatically in the background, and blocklists about every six hours. DNS changes can take time to spread, so give a new record some minutes before concluding it has not worked. ## Alerts Warmerly emails an alert when a **hard failure** appears in your records (a fail, not a warn), or when your domain or IP is newly blocklisted. Warnings such as DMARC monitor-only never trigger an alert. ## Common problems **Everything is unknown on a new mailbox.** The first checks run shortly after you connect. Wait a few minutes and use **Re-check now**. **A record shows fail but I just added it.** DNS has not spread yet, or the record was added under the wrong name. Compare it against [Email DNS records: the complete checklist](https://docs.warmerly.com/guides/dns-records). **DMARC shows warn and I have a record.** Almost always `p=none`. It is safe to leave while you are starting out. ## Related - [Email DNS records: the complete checklist](https://docs.warmerly.com/guides/dns-records) - [Deliverability checklist before you launch](https://docs.warmerly.com/guides/deliverability-checklist) - [Free deliverability tools](https://docs.warmerly.com/help/free-deliverability-tools) to check any domain without an account --- # How do inbox placement tests work? A placement test answers one question: if this mailbox sends a message right now, does it land in the inbox, in promotions or in spam? Warmerly sends a short test message from your mailbox to a small set of other mailboxes, waits, then looks in each one to see which folder the message ended up in. ## Where to run one 1. Go to **Accounts** and click the mailbox. 2. Open the **Health** tab. 3. In the **Inbox placement** card, click **Run new test**. The card shows the last time it was tested. A test takes roughly a minute: it sends the messages, waits about 30 seconds for delivery, then checks each receiving mailbox. A progress panel shows while it runs, and you can leave the page. The result is saved either way. You can also ask Warmi to run one. Because a test sends real email and uses part of your allowance, Warmi always asks for a yes first and tells you how many tests you have left. The **Run new test** button in the dashboard runs straight away, so click it deliberately. ## What it costs Each test you start uses **one of your monthly placement tests**. The allowance depends on your plan and resets on the 1st of the month. See [Plans & limits](https://docs.warmerly.com/plans-and-limits), and **Settings > Usage & limits** for how many you have used. - A test that **fails to run** (for example the mailbox cannot send) is handed back and does not count. - When you have used them all, you can wait for the reset, upgrade, or buy extra with credits from **Settings > Usage & limits**. Nothing is bought without you pressing a button that states the price. - Warmerly may also run its own automatic tests in the background. Those do not use your allowance. ## What the test sends and to whom The test sends one plain message with a subject starting **[Warmerly placement]** from your mailbox's own sending connection, so it is judged the way your real mail would be. It goes to up to four target mailboxes: some at the same provider as your mailbox and some at other providers. It is not sent to any of your leads. The mailbox must be connected and active. A paused mailbox cannot run a test: resume it first. ## Reading the result The card shows a score out of 100 and one dot per target mailbox, with a legend: | Result | Counts as | Meaning | | --- | --- | --- | | **Inbox** | 100 | Landed in the primary inbox | | **Promotions** | 60 | Filed under a promotions folder. Not a failure, not a win | | **Spam** | 10 | Went to spam or junk | | **Missing** | 0 | Never arrived. Often a sign of a stricter filter than a plain spam result | The score is the average across the targets. A number beside the score shows the change since your previous test, but only when both tests were the same kind (see the next section). Promotions is rarely reported for Gmail because Gmail's tabs are not visible to Warmerly, so a missing Promotions count does not mean nothing landed there. ### "Take this one with a pinch of salt" If the card shows this note, the test went to Warmerly's own warmup mailboxes instead of to independent Gmail, Outlook or Yahoo accounts. It tells you the message sent cleanly, but not how the big providers judge it. Those results are labelled **limited accuracy**, do not count toward your health score and are not compared against real-provider results. Treat them as a send check, not a verdict on your reputation. ## What to do with a bad result One test is a snapshot of that mailbox, on that day, at those providers. One promotions result is not an emergency. The same mailbox landing in spam repeatedly is. Work down this list: 1. Open the domain health card on the same tab. Fix any failing SPF, DKIM or DMARC ([DNS checklist](https://docs.warmerly.com/guides/dns-records)). 2. Check for a [blocklist listing](https://docs.warmerly.com/help/blocklisted). 3. Check the mailbox has warmed up. A mailbox in its first two weeks will not place well. 4. Look at your copy. Run the subject and body through the [spam word checker](https://warmerly.com/spam-word-checker), and check for too many links or images, or a brand-new tracking domain. See the [deliverability checklist](https://docs.warmerly.com/guides/deliverability-checklist). 5. Wait a few days, keep warmup on, then test again. ## Common problems **The test failed with "could not be sent".** The mailbox's mail server rejected the message. Check the connection ([Reconnect a mailbox](https://docs.warmerly.com/help/reconnect-mailbox)) and try again. It was not charged. **"Warmerly could not use this mailbox's saved password."** Reconnect the mailbox. **"This mailbox is not active".** Resume it, then run the test. **There are no target mailboxes to test against right now.** Try again later. **It says quota used up.** See [Plans & limits](https://docs.warmerly.com/plans-and-limits). ## Related - [What do my mailbox's health score and status mean?](https://docs.warmerly.com/help/mailbox-health) - [How warmup works](https://docs.warmerly.com/how-warmup-works) - [Troubleshooting](https://docs.warmerly.com/troubleshooting#placement-tests) --- # What if my domain or IP is on a blocklist? A blocklist (also called a blacklist or DNSBL) is a public list of domains and mail-server IP addresses that have been reported for spam. Mailbox providers and spam filters check these lists on every message. If your domain or the server your mail leaves from is listed, a lot of your email will be sent to spam or rejected outright until the listing is removed. Warmerly checks for listings for you. If one is found, you get an alert email (unless you turned alert emails off) and the **Health** tab of the mailbox shows **Your domain is blocklisted** or **Your mail server's IP is blocklisted**, with the list names. ## Where to see it 1. Go to **Accounts** and click the mailbox. 2. Open the **Health** tab. 3. Look at the **Blocklists** row of the domain health card. Expand it to see each list and what the listing means. For a domain check with no account, use the free [blacklist checker](https://warmerly.com/blacklist-checker). ## Which mailboxes are safe to send from right now Every mailbox in **Accounts** carries a small pill under its status: **Safe to send**, **Send with care**, **Don't send** (with the reason, such as "server listed" or "domain listed") or **Not checked yet**. The mailbox page shows the same verdict with the reason and what you can do about it. **Not checked yet** is never a clean result: it means we have no recent blocklist check, so we cannot say. **Safe to send** means none of our checks found a listing, not a guarantee of inbox placement. You can also ask Warmi "which of my mailboxes are safe to send from right now?". ## What Warmerly checks - **Six domain lists**: Spamhaus DBL, SURBL, URIBL, NordSpam, Spam Eating Monkey and s5h. - **Ten IP lists**: including Spamhaus ZEN, SpamCop, Barracuda, PSBL, Mailspike, NordSpam, Spam Eating Monkey, Lashback, DroneBL and GBUdb. Blocklists are re-checked about every six hours. **Re-check now** on the card re-reads DNS at once but may reuse a recent blocklist result. ## Which listings matter **Domain listed.** Your sending domain was reported. This is the serious one, because it follows you across every mailbox on that domain. **IP listed.** The mail server your mailbox submits through was reported. If you use Gmail or Microsoft 365, Warmerly does not check an IP for you, because your mail leaves from the provider's shared servers and you cannot delist those. If you use a small or self-hosted server, this is your address. **Policy listing (for example Spamhaus PBL).** The card says "This IP range isn't meant for sending". That means the range is a home or office connection that providers do not expect to send mail directly. It is not a report that you sent spam, and you do not request delisting. If you send through an email host, ask the host about it. **Clean on some lists, others did not answer.** Some lists refuse automated lookups sometimes. This is not a listing, and the card says how many did not answer. **Unknown.** The check could not complete. It is not a listing. It will be retried. ## What to do when you are listed 1. **Stop cold sending from that domain** while you sort it out. Keep warmup running. 2. **Find out why.** The usual causes are a purchased or old list with many bad addresses, a sudden jump in volume from a new mailbox, a compromised mailbox, or spammy links in your copy. Check your campaign's bounce rate and your recent content. 3. **Fix the cause first.** Delisting requests for a problem that is still happening are refused or the listing comes back. 4. **Request removal** on the list's own site. The blocklist row links to the right page for each list. The main ones are: - Spamhaus: [check.spamhaus.org](https://check.spamhaus.org/) - SURBL: [surbl.org/surbl-analysis](https://surbl.org/surbl-analysis) - URIBL: [uribl.com/lookup.shtml](https://uribl.com/lookup.shtml) - SpamCop: [spamcop.net/bl.shtml](https://www.spamcop.net/bl.shtml) - Barracuda: [barracudacentral.org/rbl/removal-request](https://www.barracudacentral.org/rbl/removal-request) - PSBL: [psbl.org/remove](https://psbl.org/remove) - Mailspike: [mailspike.org/iplookup.html](https://mailspike.org/iplookup.html) 5. **Wait, then re-check.** Some lists remove you within hours, others expire listings after days. Warmerly cannot remove a listing for you and cannot speed up a list's decision. If the mailbox is a OneMail mailbox that Warmerly hosts for you, the mail server IP is Warmerly's rather than yours, so ask Warmi or support instead of requesting removal yourself. See [OneMail mailboxes](https://docs.warmerly.com/help/onemail-mailboxes). ## Also from Warmerly's side If your bounce rate climbs, Warmerly slows and then pauses campaign sending on its own, which protects your domain from getting this far. See [Why did sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused). For mailboxes Warmerly hosts, our own sending addresses are watched for blocklist listings too, and a listed address is slowed down and taken out of use. See [How our email infrastructure works](https://docs.warmerly.com/infrastructure). ## Common problems **The card says listed but the list's own site says clean.** A listing may have just expired. Use **Re-check now** in a few hours. **I was delisted and it came back.** The cause is still happening. Check list quality (verify addresses before you send) and volume. **Everything says "not checked" or unknown.** The blocklists could not be queried. This is not a clean result. Try again later, or use the free checker. ## Related - [Domain health card](https://docs.warmerly.com/help/domain-health-card) - [Deliverability checklist before you launch](https://docs.warmerly.com/guides/deliverability-checklist) - [Verify emails](https://docs.warmerly.com/verify) to clean a list before sending --- # Why did my sending slow down or pause? Warmerly deliberately holds back or stops campaign sending when the numbers say your reputation is at risk. Once a domain starts landing in spam, everything from it suffers, including mail that had nothing to do with the bad list. Stopping early is far cheaper than recovering later, so Warmerly does it for you and emails you the reason. There are five separate mechanisms. Find yours below. If your mailbox page or your **Accounts** page shows a banner saying sending is limited or paused, that is the fifth. ## 1. The volume ramp (new mailboxes and new campaigns) A new mailbox is not allowed to send its full daily limit on day one. Two things hold it back: - **The warmup ramp** raises what a mailbox is allowed to do over its first 30 days. See [How warmup works](https://docs.warmerly.com/how-warmup-works). - **The campaign volume ramp** starts a campaign small and increases each sending day. It is switched on by default when a campaign is created and your mailboxes are less than 14 days into warmup, and you can change it on the campaign's **Settings** tab under **Advanced**, with the toggle **Ramp volume up gradually**. By default the first day is 3 emails per mailbox, then 1 more each sending day, up to a ceiling of 15. Weekends and other days you do not send on do not count as sending days. This is not a fault. Your mailbox's **daily sending limit** (**Settings** tab of the mailbox) is only a ceiling, and a ramp can only hold sending below it, never above. ## 2. The bounce brake (sending is throttled) If a mailbox's bounce rate over the last 7 days climbs, Warmerly cuts that mailbox's daily campaign volume before it has to stop it: | Bounce rate over 7 days | Daily volume | | --- | --- | | Under 2% | Normal | | 2% to 3% | 75% of normal | | 3% to 5% | 50% of normal | | 5% and above | 25% of normal | The brake only applies once a mailbox has sent at least 25 emails in that 7-day window, because a few bounces on a tiny sample say nothing. It never drops below 1 a day, and it releases by itself as the bounce rate falls. The fix is on the list side: [verify your addresses](https://docs.warmerly.com/verify) before you send. ## 3. Automatic pause for high bounces (campaign, then mailbox) At a bounce rate of **7% or more**, or when **30% or more of the leads tried** were rejected as undeliverable, over the last 7 days (again only after at least 25 sends), Warmerly pauses: 1. **The campaign first.** A bad list makes every mailbox that touches it look bad, and pausing the mailboxes would stop your other campaigns too. The campaign's status becomes paused. You resume it from the campaign page once the list is fixed. 2. **A mailbox next, only if it is still bad** after the bad campaigns are stopped. That means the problem follows the mailbox, not the list. You get an email with the numbers that caused the pause and what to do. The pause happens even if that email cannot be sent. ### A mailbox paused for reputation keeps warming A mailbox taken off campaigns for reputation is **not** stopped. Its status stays active, warmup keeps running (and is turned back on if it was off), and the badge on **Accounts** shows **Recovering**. The mailbox page says warmup is still running and that it will return automatically. Warmup is what rebuilds the reputation, so stopping it would remove the way back. The mailbox returns to campaigns by itself when all of these are true, checked hourly: - it has been off campaigns for at least 3 days, - it has a recent health score (from the last 3 days) of 70 or more, - its bounce rate is back under the pause level. It comes back small: 5 emails a day, climbing by 5 a day, for its first 5 days, on top of any other limit. You get an email when it returns. If you press **Resume** yourself, the same gentle return applies, because choosing to send again is not a reason to jump back to full volume. ## 4. Automatic pause when a provider refuses the message as spam If a mailbox's messages are refused by the receiving server as spam or policy (rather than because the address does not exist), those leads are **not** marked bounced and are not suppressed. They are retried later. If a mailbox gets 3 of these refusals within 24 hours, it is taken off campaigns the same way (Recovering), and you are emailed. Nothing reached your recipients and your leads are fine. Look at your copy (links, spammy phrases), check the [domain health card](https://docs.warmerly.com/help/domain-health-card) and ask your mail provider whether they are filtering outbound mail. ## 5. Slowed or paused after a rise in failed deliveries or complaints This applies to mailboxes Warmerly hosts for you (OneMail) and other mailboxes that send through our own mail servers. A mailbox you connected from your own provider, such as Gmail or Microsoft 365, sends through that provider, so this section does not apply to it. Nor does it apply to the free mailbox new accounts get, which has fixed, stricter limits instead (see [Get a free sending mailbox](https://docs.warmerly.com/help/free-sending-mailbox)). For those mailboxes, Warmerly also watches what happens to the campaign mail each one sends: how much of it bounces, how much the receiving provider refuses as spam, and how many recipients report it as spam. It looks at the last day and the last week together, and it only acts when there is enough mail to judge, and one spam report is not enough on its own, so one person pressing "report spam" does not slow your mailbox down. **For one mailbox**, it goes in steps: - Usually you first get an email saying results are slipping, while sending carries on as normal. If the numbers are already high it may go straight to slowing sending down. - If it keeps up, campaign sending from that mailbox is **slowed** to part of its usual daily volume. - If it is still bad after that, the mailbox is **paused**: it comes off your campaigns, the same way as in section 3. **For a whole workspace**, the same happens one level up when the problems are spread across its mailboxes. A workspace can be slowed, and if things do not improve, campaign sending is paused on every mailbox in it. Our team is told when that happens and may review the workspace. We will get in touch if we need anything from you. **What you see.** The mailbox page (and, for a workspace, the **Accounts** page) shows a banner that says sending is limited or paused, what was measured in plain words, and what helps. We email you (unless you have turned off alert emails) when sending is slowed or paused. **How it comes back.** Warmup keeps running the whole time, which is what rebuilds a mailbox's reputation. As the results stay healthy, sending is raised a step at a time, about a day apart, until it is back to normal. If our team is reviewing your workspace, it returns once that review is done. A paused mailbox returns the same way as in section 3, starting at a low volume. If our team changes your sending limits by hand, you get an email when they change them and another when they lift them. **What helps:** - Check the addresses before they go out again. [Verify](https://docs.warmerly.com/verify) flags the ones that no longer exist. - Remove old or purchased contacts. Lists that have sat for months, or were bought, are where most bounces and complaints come from. - Send fewer emails for a few days. Smaller, steady volumes recover faster than big bursts. - Review the content: links to new or shortened domains, attachments, heavy formatting and salesy phrases are what filters react to. Write only to people who are likely to want to hear from you, and make it easy to opt out. If something in the banner or the email looks wrong, write to support@warmerly.com and a person will look at it. ## Other reasons sending stops that are not reputation - **The mailbox is Paused or Disconnected.** See [What do my mailbox's health score and status mean?](https://docs.warmerly.com/help/mailbox-health) and [Reconnect a mailbox](https://docs.warmerly.com/help/reconnect-mailbox). A health score under 60 for two days also pauses a mailbox entirely, and it resumes itself after about three days. - **Billing or plan limits.** See [Plans & limits](https://docs.warmerly.com/plans-and-limits). - **Outside the sending window or days.** See the [troubleshooting checklist](https://docs.warmerly.com/troubleshooting#a-campaign-is-not-sending). ## What Warmerly does not do - It does not pause on inbox placement results, because a placement test is too small a sample to stop your sending automatically. It acts on bounces, provider refusals and spam reports (section 5). - It only counts spam reports that reach it. Most providers, Gmail included, never tell the sender who pressed "report spam", so a low count here does not prove nobody did. - It cannot un-pause a campaign for you. Campaign pauses are resumed by you. ## Common problems **"My mailbox says Recovering and I did not do anything."** That is one of the automatic pauses above. If the mailbox page shows a banner, it says which and why. An automatic pause returns by itself once the mailbox is healthy again, and the tips in section 5 get it there faster. If only one mailbox is affected, your other mailboxes keep sending. **"The banner says sending is paused across my workspace."** That is the workspace level of section 5: campaign sending is paused on every mailbox in it, and warmup keeps running on all of them. The mailboxes return to campaigns once they are healthy again, and our team has been told and may review it. **"I resumed the mailbox and it barely sends."** The return ramp is 5 emails a day, rising by 5, for 5 days. That is intentional. **"The brake is throttling a mailbox but my list is fine."** Bounces count from any campaign that mailbox sent in the last 7 days, and hard bounces from old addresses are the usual cause. ## Related - [How our email infrastructure works](https://docs.warmerly.com/infrastructure): learn how our infrastructure protects reputation - [Launch your first campaign](https://docs.warmerly.com/help/launch-first-campaign) - [Deliverability checklist before you launch](https://docs.warmerly.com/guides/deliverability-checklist) - [Suppression list](https://docs.warmerly.com/suppression) --- # My mailbox won't connect: Gmail, Microsoft 365 and other providers Start from the error you see, or from your provider. This page points to the exact fix, and the detailed steps live in the pages it links to. Warmerly signs in to **both** SMTP (to send) and IMAP (to read) before it saves a mailbox, so a mailbox that connects here will work for real. Use **Test connection** on the setup form before saving. It tells you which of the two failed. ## Find your provider | Provider | How it connects | If it fails, go to | | --- | --- | --- | | **Gmail and Google Workspace** | Google app password (not your normal password) | [App password guide](https://docs.warmerly.com/guides/mailbox-connection#gmail-and-google-workspace-app-password). If Google says the setting is "not available for your account", see [2-Step Verification and Workspace admins](https://docs.warmerly.com/guides/mailbox-connection#google-workspace-the-setting-you-are-looking-for-is-not-available-for-your-account) | | **Microsoft 365, Outlook.com, Hotmail** | One-click Microsoft sign-in | [Outlook sign-in errors](https://docs.warmerly.com/troubleshooting#outlook--microsoft-365-we-could-not-finish-connecting-your-outlook-account), [SMTP username or password failed after sign-in](https://docs.warmerly.com/troubleshooting#microsoft-365-smtp-username-or-password-failed-but-oauth-reconnected-fine) | | **Zoho, Namecheap Private Email, IONOS, Hostinger, others** | Manual SMTP and IMAP settings | [Manual setup and host and port table](https://docs.warmerly.com/guides/mailbox-connection#manual-setup-zoho-mail-namecheap-private-email-or-any-other-provider) | | **OneMail and the free mailbox** | Hosted by Warmerly, no password to enter | [OneMail](https://docs.warmerly.com/help/onemail-mailboxes), [Free mailbox](https://docs.warmerly.com/help/free-sending-mailbox) | ## What each message means | You see | What it means | What to do | | --- | --- | --- | | "Wrong username or password" | The login was refused | Recheck the address and password. If the mailbox has two-step sign-in, it needs an app password | | "needs an app password, not the password you sign in with" | Two-step sign-in is on | Create an app password and paste that | | "The provider blocked this sign-in as unusual" | The provider wants you to confirm it was you | Sign in to webmail in a browser, confirm, then retry | | "Microsoft has SMTP sending switched off" | Authenticated SMTP is disabled for your Microsoft 365 organisation | An admin has to enable it. See [Microsoft 365 troubleshooting](https://docs.warmerly.com/guides/mailbox-connection#microsoft-365-authentication-unsuccessful-after-a-successful-reconnect) | | "Couldn't reach the mail server" | Host or port wrong, or the server is down | Check the host and port for your provider | | "Secure-connection problem, the port may be wrong" | Wrong port for the encryption type | Try 465 or 587 for SMTP | | "The provider is temporarily blocking logins" | Too many attempts in a short time | Wait a few minutes and try again | ## Microsoft 365 in a few lines - Warmerly uses SMTP and IMAP over Microsoft sign-in (it does not send through Microsoft Graph). Exchange needs the username to be the mailbox's **primary SMTP address**, which can differ from the sign-in address. A reconnect re-reads the correct address. - **SMTP AUTH turned off** for the organisation looks like a credentials error even though sign-in worked. Only a tenant admin can turn it on. - **"Need admin approval"** from Microsoft before you get back to Warmerly means your organisation only lets administrators approve new apps. Ask an admin to approve Warmerly. - Aliases, shared and delegated mailboxes work if the signed-in user has Send As or Full Access rights and you set the SMTP and IMAP username to that mailbox address. ## Google in a few lines - Gmail and Workspace use an **app password**, which only appears once 2-Step Verification is on. On Workspace an administrator may need to allow 2-Step Verification first. - If the app password is later deleted or your Google password changes, the mailbox disconnects. Create a new app password and use **Reconnect**. ## It was working and then stopped That is a disconnect, not a setup problem. See [Why did my mailbox disconnect, and how do I reconnect it?](https://docs.warmerly.com/help/reconnect-mailbox). A wrong password is never retried automatically. If the mail server was only unreachable, Warmerly retries on its own about every 30 minutes. ## Still stuck Ask Warmi in the chat widget. It can see your mailbox's status and the reason for the last failure. If you add a mailbox by SMTP and IMAP and nothing above helps, contact support with the exact message shown. ## Related - [Connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection) - [Troubleshooting](https://docs.warmerly.com/troubleshooting) - [What do my mailbox's health score and status mean?](https://docs.warmerly.com/help/mailbox-health) --- # What free email deliverability tools does Warmerly have? Warmerly publishes seven free tools on [warmerly.com/tools](https://warmerly.com/tools). You do not need an account, and none of them sends an email. They tell you what is true about a domain or a draft today. For the same checks run automatically on your connected mailboxes, with alerts when something breaks, use the **Health** tab of a mailbox ([domain health card](https://docs.warmerly.com/help/domain-health-card)). ## The tools | Tool | Use it to | Link | | --- | --- | --- | | **Deliverability checker** | Check any domain's SPF, DKIM, DMARC and MX records in one go, with plain-English fixes. No test email is sent | [warmerly.com/deliverability-checker](https://warmerly.com/deliverability-checker) | | **SPF record checker** | Validate an SPF record: a single record, the 10 DNS lookup limit, and a safe ending (not `+all` or `?all`) | [warmerly.com/spf-checker](https://warmerly.com/spf-checker) | | **DKIM checker** | Look up a DKIM key by selector and check its key type, size and whether it is still in test mode (`t=y`) | [warmerly.com/dkim-checker](https://warmerly.com/dkim-checker) | | **DMARC checker** | Look up a DMARC policy (none, quarantine or reject), its reporting address, `pct` and alignment | [warmerly.com/dmarc-checker](https://warmerly.com/dmarc-checker) | | **Email blacklist checker** | Check a domain, or a mail server IP, against Spamhaus, SURBL, URIBL, SpamCop and other lists, with removal links | [warmerly.com/blacklist-checker](https://warmerly.com/blacklist-checker) | | **Spam word checker** | Scan a subject line and body for spam-trigger phrases and get a risk score with rewrite tips | [warmerly.com/spam-word-checker](https://warmerly.com/spam-word-checker) | | **Email HTML checker** | Check text-to-HTML ratio, image and link counts and tracking pixels in a draft. Runs in your browser | [warmerly.com/email-html-checker](https://warmerly.com/email-html-checker) | | **Warmup calculator** | Get a day-by-day sending ramp based on mailbox age, provider and target volume | [warmerly.com/warmup-calculator](https://warmerly.com/warmup-calculator) | ## Which one for which problem - **"Is my domain set up properly?"** Start with the deliverability checker, then use the SPF and DMARC checkers for a closer look. Fix guides: [DNS checklist](https://docs.warmerly.com/guides/dns-records), [DKIM](https://docs.warmerly.com/guides/dkim), [SPF & DMARC](https://docs.warmerly.com/guides/spf-dmarc). - **"My email is going to spam."** Run the blacklist checker, then the spam word checker on your copy, then the HTML checker on your template. - **"How fast should I ramp a new mailbox?"** Use the warmup calculator to see a schedule, then see [How warmup works](https://docs.warmerly.com/how-warmup-works) for how Warmerly's own ramp behaves. ## What the free tools cannot do - **The blacklist checker uses the same lists and rules as Warmerly's own checks.** A list that could not answer is shown as unknown or not checked, never as clean. - **They are point-in-time.** A checker tells you the answer right now. Warmerly's Health tab re-checks DNS regularly and blocklists about every six hours, and alerts you. - **The spam word checker and HTML checker are guides, not verdicts.** Inbox providers do not publish their filters. A low score does not guarantee delivery, and a high one is a reason to reword, not proof of spam. - **They do not read your mailbox or send test mail.** To see where a real message lands, run a [placement test](https://docs.warmerly.com/help/placement-tests) from a connected mailbox. - **The DKIM check may not find a custom selector.** DKIM is found by trying common selector names. See [Troubleshooting](https://docs.warmerly.com/troubleshooting#dkim-shows-missing-but-the-record-exists). ## Warmerly also checks copy for you When you start a campaign, Warmerly runs a readiness check that can warn about sender DNS that is not passing, too many mailboxes on one domain, tracking without a verified tracking domain, and email copy with a high spam score, many links or many images. These are warnings you can acknowledge, not blocks. See [Launch your first campaign](https://docs.warmerly.com/help/launch-first-campaign). ## Related - [Deliverability checklist before you launch](https://docs.warmerly.com/guides/deliverability-checklist) - [Domain health card](https://docs.warmerly.com/help/domain-health-card) - [What if my domain or IP is on a blocklist?](https://docs.warmerly.com/help/blocklisted) --- # How do I connect LinkedIn and send LinkedIn outreach? You connect a LinkedIn account from **Accounts**, then use it in a campaign as a sender. Each connected LinkedIn account needs its own paid slot, called a **Warmerly Link** slot. LinkedIn is not included in any base plan, and there is no free trial for it. Warmerly acts through your own LinkedIn profile, so the connection requests and messages come from you. For the price, see [Plans & limits](https://docs.warmerly.com/plans-and-limits) or the [pricing page](https://warmerly.com/pricing). For how slots work, see [Channel accounts: paid slots and overage](https://docs.warmerly.com/help/channel-slots). ## Connect a LinkedIn account 1. Open **Accounts** and click **Add**. 2. Under "Or add another channel", choose **LinkedIn account**. 3. The screen shows how many paid LinkedIn slots you are using. If every slot is taken (or you have none), the button becomes a purchase button instead. Buy a slot first, then come back. 4. Click **Continue to LinkedIn**. LinkedIn's own sign-in opens. Log in, and approve the login on your phone if LinkedIn asks. 5. You return to **Accounts**, where the account is listed under the **LinkedIn** tab as **Active**. Only people with billing permission in the workspace can buy a slot. Inside an Agency client workspace, slots are bought in the main (parent) workspace. ## What you see on the LinkedIn tab Each connected account shows its name, headline, a **Premium** badge if the LinkedIn account has a paid LinkedIn plan, its send window (hours and timezone), and two bars: - **Connections**: connection requests sent today against the account's daily limit. - **Messages**: direct messages sent today against the account's daily limit. Buttons on the right reconnect or disconnect the account. A **LinkedIn warmup settings** section under each account controls warmup (see [LinkedIn warmup](https://docs.warmerly.com/help/linkedin-warmup)). Warmerly also applies a separate safety budget per account, so a send can wait even when the bars show room. See "Daily limits" below. ## Send outreach in a campaign 1. Create or open a campaign (see [Launch your first campaign](https://docs.warmerly.com/help/launch-first-campaign)). 2. In the **Sequence** editor, add **LI Connection** (a connection request) and **LI Message** (a direct message) steps. A connection request note is optional and limited to 300 characters. 3. Open the campaign's **Senders** tab. Under **LinkedIn accounts**, pick your account from "Add a LinkedIn account" and add it. Without a sender, LinkedIn steps cannot run. 4. Get leads that have a LinkedIn profile into the campaign, for example with [Warmerly Link](https://docs.warmerly.com/help/warmerly-link). A lead with no LinkedIn profile is skipped on a message step. 5. Launch. The launch checklist blocks the campaign if a LinkedIn step has no sender or no active Warmerly Link slot. A campaign can mix email and LinkedIn steps in one sequence. WhatsApp steps cannot be launched yet, see [WhatsApp outreach](https://docs.warmerly.com/help/whatsapp-outreach). Replies from LinkedIn arrive in the shared **Inbox** next to your email conversations. ## Daily limits Every LinkedIn action draws from one daily budget per account, shared by warmup and campaigns. The budget grows as the account builds up activity, so a new account starts small on purpose. - Connection requests: 2 a day on a normal LinkedIn account, 10 a day on LinkedIn Premium, at full pace. A weekly ceiling applies on top. - Messages: up to 50 a day at full pace. - The budget starts at a fraction of full pace and rises over roughly three weeks of warmup days. When the budget for the day is used up, remaining steps wait and resume the next day. Nothing is lost. The days that count towards the ramp are days LinkedIn warmup actually ran, so turning warmup on is what raises the budget. See [LinkedIn warmup](https://docs.warmerly.com/help/linkedin-warmup). These limits protect your LinkedIn account. They cannot be raised past the safe maximums, and support cannot lift them. ## My LinkedIn account shows Disconnected The status on each account is **Active**, **Reconnecting** or **Disconnected**. Disconnected means LinkedIn stopped accepting Warmerly's session, usually because the LinkedIn password changed, the account logged out everywhere, or LinkedIn asked for an extra verification step. 1. Open **Accounts**, then the **LinkedIn** tab. 2. Click **Reconnect** on the account. 3. Sign in on LinkedIn's screen again and approve the login on your phone if asked. Reconnecting repairs the same account in place, so your warmup settings and campaign links stay. Warmerly also re-checks accounts that are not Active whenever you open the tab, so a stale Disconnected label can fix itself. While an account is disconnected, its warmup and campaign steps do not run. ## Disconnect or remove an account Click the bin icon on the account and confirm. Warmerly stops using it and removes it from your workspace. The slot it used becomes free, so you can connect a different LinkedIn account with it. Disconnecting does not cancel the slot subscription, so you keep paying for the slot until you cancel it. ## Common problems - **A purchase button instead of Continue to LinkedIn.** You have no free slot. Buy one from the wizard or from **Settings > Usage & limits** (the Warmerly Link slots card). - **LinkedIn did not accept the email or password.** Check them and try again. - **LinkedIn wants an extra verification step.** Open the LinkedIn app, approve the login, then try again. - **Too many attempts.** Wait a few minutes before trying again. - **Campaign not sending on LinkedIn.** Check that the account is Active, is added on the Senders tab, its slot is not past due or ended, and your workspace is not billing-locked. A billing-locked workspace pauses LinkedIn warmup and campaign sending along with email. - **The slot ended.** When a slot subscription ends, Warmerly disconnects and removes the linked LinkedIn account at that point. Cancelling a slot keeps it working until the end of the period you already paid for. --- # What is LinkedIn warmup and how do I turn it on? LinkedIn warmup runs your connected LinkedIn account the way an active person would: viewing profiles, reacting to posts, writing comments, publishing the odd post, and sending a few connection requests, spread across your working hours. A brand-new or long-dormant account that suddenly sends lots of invitations looks automated and gets restricted. Warmup builds the activity first, and outreach shares the same daily budget. It is different from email warmup. There is no peer network and no other Warmerly users involved. Everything happens on your own LinkedIn account. See [How warmup works](https://docs.warmerly.com/how-warmup-works) for the email side. **Warmup is off by default.** When you connect an account, its warmup starts paused. You switch it on yourself. ## Turn it on 1. Open **Accounts** and the **LinkedIn** tab. 2. On the account, expand **LinkedIn warmup settings**. 3. Switch on **Run warmup automatically**. This saves immediately. 4. Fill in the fields below so the posts and comments sound like you, then save. The fields: - **Post and comment guidelines**: your voice, audience, offers, and topics to avoid. - **Topics**: comma separated, for example "cold email, deliverability". - **Industries**: comma separated. Warmerly writes posts and comments with AI from those settings, and searches posts and people in your topics and industries to react to and connect with. The more specific the topics, the better the activity fits your profile. ## What it does each day Once a day, inside the account's send window and timezone, Warmerly plans a set of actions and spaces them out through the day with some random spread: - publishes an original post - reacts to posts in your topics - comments on posts in your topics - views profiles of people in your topics - sends connection requests to a few of those people At full pace the caps are up to 40 profile views, 20 reactions, 5 comments and 2 posts a day, plus the connection request limits described in [How do I connect LinkedIn](https://docs.warmerly.com/help/linkedin-outreach). ## How the ramp works Volume starts small and rises as warmup days accumulate: about a fifth of full pace for the first 3 days, then roughly a third, about half, three quarters, and full pace from about day 22. A day counts when warmup actually ran on it, so days when warmup was off or paused do not move the ramp forward. Campaign steps on the same account draw from the same daily budget. Outreach can never push the account past what warmup has earned. Caps can only be lowered, never raised past the safe maximums. ## When warmup pauses itself If LinkedIn reports a restriction, a checkpoint, a rate limit or an invalid session, Warmerly pauses warmup on that account as a safety step. To resume, first fix the cause (for example reconnect the account, see [LinkedIn outreach](https://docs.warmerly.com/help/linkedin-outreach)), then switch **Run warmup automatically** on again. Warmup also does not run when: - the account is Disconnected - its slot is past due, or has ended - your workspace is billing-locked or suspended If the AI writing step returns nothing for a post or comment, that one action is skipped and the rest of the day carries on. ## Common problems - **Nothing is happening on my account.** Check that **Run warmup automatically** is on, the account is Active, and the slot is paid up. Actions are planned for the account's working-hours window, so the first ones do not appear instantly. - **I turned it on, but posts do not match my business.** Add specific guidelines, topics and industries and save. The changes apply to the next planned day. - **Can I run warmup without the paid slot?** No. Warmup and sending both need a slot. See [Channel accounts: paid slots and overage](https://docs.warmerly.com/help/channel-slots). - **Does warmup guarantee my account will not be restricted?** No. It lowers the risk by keeping behaviour human-like and inside safe limits. LinkedIn decides what counts as a violation. --- # What is Warmerly Link? Warmerly Link is Warmerly's LinkedIn product. The name shows up in two places: - **The paid slot.** Each connected LinkedIn account needs one Warmerly Link slot, sold separately from your plan. A slot covers warmup, automated outreach, prospect search and import, and the shared inbox for that one account. See [Channel accounts: paid slots and overage](https://docs.warmerly.com/help/channel-slots) and [Plans & limits](https://docs.warmerly.com/plans-and-limits) for cost. - **The page.** **Warmerly Link** in the sidebar, under **Outreach**, is where you search LinkedIn for people and push them into a campaign. ## What you need first The **Warmerly Link** page shows one of three things: 1. **"Warmerly Link needs a paid slot."** You have no LinkedIn slot. The page explains warmup and automation, and **View plans** takes you to **Settings > Billing**. 2. **"Connect a LinkedIn account to get started."** You have a slot but no connected account. Click **Connect LinkedIn account** to go to **Accounts**, or follow [How do I connect LinkedIn](https://docs.warmerly.com/help/linkedin-outreach). 3. **The search screen.** You have a slot and a connected account. Searches run through your own connected LinkedIn account (the first Active one whose slot is paid). If that account is disconnected, the page tells you to reconnect it. ## Find people (hand-pick) 1. Choose a **Campaign** at the top. If you have none, there is a link to create one. 2. Leave the mode on **Hand-pick**. 3. Type **Keywords**, such as a job title and industry ("Head of Growth SaaS"). 4. Optionally open the filters: **Location**, **Industry**, **Current company**, and connection distance (1st, 2nd, 3rd+). 5. Search. Each page shows 15 people. Tick the ones you want, then import them into the campaign. People already in the campaign are skipped, and the message tells you how many. If the campaign has email senders, Warmerly also tries to find an email address for each imported person. Each of those lookups uses your email lookup allowance. If the allowance runs out, the people are still imported, they just wait without an email. ## Bulk import Switch the mode to **Bulk import** to pull many results from one search without ticking each: 1. Set your keywords and filters. 2. Under **How many leads**, choose 250, 500, 1,000, 5,000 or All. 3. Start the import and leave the page open to watch progress. The job stops early, and says why, if the campaign reaches its lead limit or you run out of your monthly LinkedIn lookups. Everything imported up to that point stays in the campaign. ## What counts against your allowance Every search page, and every page a bulk import fetches, uses one **LinkedIn lookup** from your monthly allowance. A failed search costs nothing. The allowance depends on your plan and resets on the 1st. See your usage under **Settings > Usage & limits**, and [Usage & limits](https://docs.warmerly.com/usage). When you run out, Warmerly refuses the search and shows a message. You can top up with credits from **Settings > Usage & limits** (see [Plans & limits](https://docs.warmerly.com/plans-and-limits)), or wait for next month. ## Sending to the people you import Importing only adds leads. To contact them, the campaign needs LinkedIn steps and your LinkedIn account added as a sender. See [How do I connect LinkedIn](https://docs.warmerly.com/help/linkedin-outreach#send-outreach-in-a-campaign). ## Common problems - **The sidebar item leads to a "needs a paid slot" page.** That is expected without a slot. - **"No LinkedIn account".** The account is disconnected or its slot is not active. Reconnect it from **Accounts > LinkedIn**. - **Search fails with a limit message.** You used the month's LinkedIn lookups. - **Results look thin.** Use fewer, more specific keywords, or add a location or industry filter. Warmerly cannot see anything LinkedIn does not show your own account. --- # How do I connect WhatsApp and how many messages can I send? You link your own WhatsApp number to Warmerly by scanning a QR code, the same way you link WhatsApp on a computer. Once linked, its conversations appear in the **Inbox**, and you can message from it. How many numbers you can link depends on your plan plus any WhatsApp slots you buy. See [Channel accounts: paid slots and overage](https://docs.warmerly.com/help/channel-slots). **There is no WhatsApp warmup.** Email needs warmup because inbox providers keep a reputation score. WhatsApp has no such score to build. What WhatsApp does is watch behaviour: how new the number is, how fast it sends, and how many strangers block or report it. So Warmerly does not warm a number. Instead it limits how fast a number can send, automatically (see "How many messages a day" below). ## Link a number 1. Open **Accounts** and click **Add**. 2. Under "Or add another channel", choose **WhatsApp**. 3. The screen shows how many WhatsApp numbers are in use. If all covered numbers are taken, it offers to buy a slot instead. If your plan includes none, you need a slot first. 4. Click **Start WhatsApp setup**. A **Connect WhatsApp** window opens with a QR code. 5. On your phone open WhatsApp, then **Settings > Linked Devices > Link a Device**, and scan the code. 6. The window says **Connected!** and the number appears under **Accounts > WhatsApp**. The status shows **Connecting...**, **Scan QR**, then **Connected**. If it says **Connection failed**, click **Try again** for a fresh QR code. If you have a link in progress, Warmerly reuses it instead of starting a second one. Old conversations from before you linked are brought into the Inbox once, shortly after linking. Group chats and broadcast lists are not imported, only one-to-one chats. ## Use WhatsApp - **Inbox.** Messages sent and received on the linked number appear in **Inbox**. Reply from there, or start a new WhatsApp message from the compose window by choosing WhatsApp and typing a phone number. - **Campaigns.** WhatsApp cannot be used in a campaign yet. The sequence editor lets you add a **WhatsApp** step, but there is no way to choose which WhatsApp number a campaign sends from, so the launch checklist fails with "WhatsApp sending isn't available for campaigns yet" and the campaign cannot launch until you remove the step. Use the Inbox to message on WhatsApp. Messages you type yourself in the Inbox are never held back by the send window or spacing below. They do count towards the number's messages for the day, though. ## How many messages a day This is automatic. You do not have to set anything. The window and spacing below are built for campaign sends, which cannot be launched for WhatsApp yet (see above), so today they matter mainly for the daily volume and the limits protecting the number. A newly linked number starts low and climbs as it actually sends: - The default start is 5 messages on the first sending day. - It rises by 3 for each day the number really sends on. - The default ceiling is 40 a day, reached on the 13th sending day. Days when the number sent nothing do not count, so a number sitting idle stays at its starting volume. Running a second campaign does not restart the ramp, because WhatsApp judges the number, not the campaign. Campaign messages are also: - **Sent inside a window.** Default 9:00 to 17:00 in the number's timezone, which starts as your workspace's default timezone. - **Spaced out.** By default at least 5 minutes apart, plus a random extra of up to 3 minutes, so it does not look like a bot. - **Capped by a hard daily ceiling.** Default 75, and the ramp can never push past it. **Accounts > WhatsApp** shows "Messages today" against the cap in force now, not against the ceiling. ## Change the pacing (only to go slower) Click the sliders icon (Sending settings) on a number to change the ramp start, step and ceiling, the gap and random extra, the send window and timezone, and the hard daily ceiling. Warmerly manages all of this for you already. Use the settings only if you want to be more cautious. The window must end after it starts, and the ramp ceiling cannot be below its starting volume. **Restart the ramp from day 1** treats the number as newly linked. Use it after a number has come back from a WhatsApp block. Warmerly does this by itself when it detects that WhatsApp blocked or logged out the number. ## Common problems - **My number was blocked or logged out.** That is WhatsApp's decision, and neither Warmerly nor support can lift it. Relink the number from **Accounts > WhatsApp** and let the ramp rebuild. Blocks usually last 24 to 48 hours, and repeat offences can become permanent. - **Disconnected.** Use the reconnect button on the number. It resets the session and shows a new QR code to scan. Logging the linked device out from your phone also ends the session. - **Over the limit, or the workspace is locked.** You have more numbers than your plan and slots cover. Buy a slot or unlink a number, see [Channel accounts: paid slots and overage](https://docs.warmerly.com/help/channel-slots). - **A message I typed in the Inbox did not send.** Check that the number shows **Connected** under **Accounts > WhatsApp**, and that your workspace is not over its limits. A billing lock never blocks replies you type yourself. - **Can I send unlimited bulk WhatsApp?** No. Volume stays inside what WhatsApp tolerates, and the limits protect your number. --- # Channel accounts: paid slots and overage LinkedIn and WhatsApp accounts are paid for with **slots**. A slot is a small subscription that covers one connected account. You buy the slot first, then connect the account. Nothing is ever charged automatically because you connected one more account than you had paid for. Instead, Warmerly refuses the connection and offers to sell you a slot. Prices are not listed on this page because they can change and depend on your billing currency. See [Plans & limits](https://docs.warmerly.com/plans-and-limits) or the [pricing page](https://warmerly.com/pricing), and the button on the slot card shows the exact amount before you buy. ## Slots at a glance | Channel | What is included in your plan | How you get more | | --- | --- | --- | | Email mailboxes | A number set by your plan | Upgrade, or use [OneMail](https://docs.warmerly.com/help/onemail-mailboxes) mailboxes, which never use a plan mailbox slot | | LinkedIn (Warmerly Link) | None. Every plan includes zero | One paid slot per LinkedIn account | | WhatsApp numbers | Depends on the plan. Starter includes none | One paid slot per extra number | Monthly allowances such as email verifications, LinkedIn lookups and AI credits are a different kind of limit. They reset on the 1st and are explained in [Usage & limits](https://docs.warmerly.com/usage). ## LinkedIn (Warmerly Link) slots - One slot covers one LinkedIn account: its warmup, its automated outreach, prospect search and import, and its messages in the shared Inbox. - LinkedIn is charged immediately when you buy a slot, with no free trial, even if your workspace is still on a plan trial. **LinkedIn accounts are non-refundable.** - Buy more than one for less per account: a **3-account pack** ($49/month, $16.33 each) or a **5-account pack** ($75/month, $15 each), against $19 for one. The price is shown in dollars, pounds or euros depending on where you are billed (£39 and £59, €45 and €69 for the packs). A pack is one subscription: its slots start, renew and end together, so cancelling one cancels the whole pack at the end of the period. - The slot is tied to an account once you connect one. If you disconnect the account, the slot is free again and you can connect a different LinkedIn account with it. The slot keeps billing until you cancel it. - Cancelling a slot takes effect at the end of the period you already paid for. It keeps working until then. At the end, Warmerly disconnects the LinkedIn account that was using it and removes it from your workspace. There is no refund for the rest of a period. - If a slot payment fails, the slot becomes past due and stops covering the account. Warmup and campaign steps on that account stop until the payment is fixed. - On an Agency plan, slots you buy are shared by the workspace and its client workspaces. Buy them in the main (parent) workspace, not inside a client workspace. ### Buy a LinkedIn slot 1. Open **Settings > Usage & limits** and find the **Warmerly Link slots** card, or start from **Accounts > Add > LinkedIn account** when every slot is in use. 2. Click the **Buy ... slot** button. You go to a secure checkout that asks for a billing address and, if you are a business, an optional tax ID. 3. After payment you return to **Accounts > LinkedIn**. Continue with [How do I connect LinkedIn](https://docs.warmerly.com/help/linkedin-outreach). Only people with billing permission in the workspace can buy or cancel a slot. To cancel one, use the **Cancel** button on its row in the same cards, described under "How do I cancel a slot?" below. ## WhatsApp slots - The number of WhatsApp numbers you can link is what your plan includes plus the slots you have bought. **Settings > Usage & limits** shows it on the **WhatsApp numbers** card, for example "2 on your plan + 1 purchased". - Slots are bought **before** you link the number. If you are using every covered number, linking another is refused with a message and a **Buy ... slot** button. - The same rule applies during a trial. There is no free extra number on trial. - The count is for the whole workspace, not per person. - A purchased slot is only tied to a specific number once you are past what your plan includes. - If you cancel a WhatsApp slot (the **Cancel** button on its row), it keeps covering the number until the end of the period you paid for. The number is not disconnected. Warmerly then checks whether your workspace is above what it is covered for. If it is, the normal over-limit grace period starts, and you can buy the slot again or unlink a number. See [How do I connect WhatsApp](https://docs.warmerly.com/help/whatsapp-outreach) for linking and pacing. ## What happens if I have more accounts than I have paid for The **Settings > Usage & limits** cards say "without a slot" (LinkedIn) or "not covered" (WhatsApp). This gives you a grace period to buy a slot or disconnect the extra account. If nothing changes, the workspace locks: sending and warmup pause until you are back inside your limits, without deleting anything. The lock and the grace period work the same way as any other plan limit, described in [Plans & limits](https://docs.warmerly.com/plans-and-limits). Disconnecting the extra account clears the lock straight away. ## Common problems - **"Purchase a slot before connecting."** You have no free LinkedIn slot. Buy one, or disconnect an account to free one. - **"Your plan includes no WhatsApp numbers."** Starter includes none. Buy a slot, or move to a plan that includes numbers. - **"You're using all N of your WhatsApp numbers."** Buy another slot or unlink a number. - **I bought a slot but cannot connect.** The slot becomes usable once Stripe confirms the payment. Reload **Settings > Usage & limits** and check the card count, and contact support if it still shows no slot after a few minutes. - **How do I cancel a slot?** Open **Settings > Usage & limits**. The **Warmerly Link slots** and **WhatsApp numbers** cards list each paid slot with a **Cancel** button. Click it and read the confirmation, which shows the date the slot ends and what happens to the account. Confirm with **Cancel slot**. The slot then shows **Ends on** and that date, and keeps working until then. You are not billed again and there is no refund for the rest of the period. A LinkedIn account covered by the slot is disconnected on that date. A WhatsApp number is not disconnected. Only people with billing permission can cancel. The slot can also be cancelled from **Settings > Billing** with **Manage billing**, where each slot is a separate subscription from your plan. There is no undo button on the card. If you cancelled by mistake before the end date, contact support. Cancelling your base plan is a separate action, see [Cancel or change your plan](https://docs.warmerly.com/help/cancel-or-change-plan). - **Can support raise the daily sending caps?** No. The daily caps on LinkedIn and WhatsApp exist to protect your accounts from being restricted or blocked, and they are not adjustable upwards. --- # Which channels can I connect and send from? Warmerly is an outreach product, and the channels you can connect and send from are: - **Email**: your own mailboxes, hosted [OneMail](https://docs.warmerly.com/help/onemail-mailboxes) mailboxes and the [free sending mailbox](https://docs.warmerly.com/help/free-sending-mailbox) - **LinkedIn**: see [How do I connect LinkedIn](https://docs.warmerly.com/help/linkedin-outreach) - **WhatsApp**: see [How do I connect WhatsApp](https://docs.warmerly.com/help/whatsapp-outreach) **Accounts** shows tabs for **All**, **Mailboxes**, **LinkedIn** and **WhatsApp**. Warmerly does not run your social media posting, comment moderation or ad accounts. ## What you can connect | Channel | Status | Where to connect it | What it covers | | --- | --- | --- | --- | | Email | Live | **Accounts** | Warmup and campaigns on every mailbox. See [Connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection). | | LinkedIn | Live | **Accounts > Add > LinkedIn account** | Warmup, connection requests and messages through your own profile. Needs a paid slot per account. | | WhatsApp | Live | **Accounts > Add > WhatsApp** | Linking a number by QR code, and one-to-one messaging from the Inbox. | ## Limits and pacing on the live channels Warmerly sets these to protect your accounts. You can make them slower, never faster. - **Email.** New mailboxes warm up before they carry full volume. See [How warmup works](https://docs.warmerly.com/how-warmup-works). - **LinkedIn.** Connection requests are limited to 2 a day on a normal LinkedIn account and 10 a day on LinkedIn Premium at full pace, with a weekly ceiling on top. Messages are limited to 50 a day at full pace. The budget starts smaller and grows over roughly three weeks of warmup days. Support cannot lift these limits. - **WhatsApp.** A number starts at 5 messages on its first sending day and adds 3 for each day it really sends on, up to 40 a day, under a default hard ceiling of 75. Campaign messages go out between 9:00 and 17:00 in the number's timezone, at least 5 minutes apart plus up to 3 random minutes. There is no WhatsApp warmup. LinkedIn and WhatsApp accounts are covered by plan allowances and paid slots, see [Channel accounts: paid slots and overage](https://docs.warmerly.com/help/channel-slots). ## What is not supported - Posting or scheduling content on social platforms. - Direct messages on social platforms other than LinkedIn and WhatsApp. - Comment moderation, reviews or ad accounts on any social platform. - WhatsApp as a campaign step. The sequence editor lets you add one, but the launch checklist blocks the campaign, so message on WhatsApp from the Inbox instead. - WhatsApp group chats and broadcast lists. Only one-to-one chats are imported. ## If you want outreach on social platforms Two things work today: - **LinkedIn outreach** through your own LinkedIn profile, with warmup, connection requests and messages. See [What is Warmerly Link?](https://docs.warmerly.com/help/warmerly-link). - **WhatsApp messaging** from your own number, in the Inbox. See [WhatsApp outreach](https://docs.warmerly.com/help/whatsapp-outreach). ## Common problems - **Will more channels be added?** There is no date to promise here. Follow the [changelog](https://docs.warmerly.com/changelog) for what ships. ## Troubleshooting the channels that do work - **LinkedIn shows Disconnected.** Open **Accounts**, then the **LinkedIn** tab, and click **Reconnect**. Your warmup settings and campaign links stay. See [How do I connect LinkedIn](https://docs.warmerly.com/help/linkedin-outreach). - **The LinkedIn button asks me to buy something.** Every paid slot is in use. Buy one, then connect again, see [Channel accounts: paid slots and overage](https://docs.warmerly.com/help/channel-slots). - **WhatsApp shows Connection failed.** Click **Try again** for a fresh QR code, and scan it from **Settings > Linked Devices > Link a Device** in WhatsApp on your phone. See [How do I connect WhatsApp](https://docs.warmerly.com/help/whatsapp-outreach). - **WhatsApp was blocked or logged out.** That is WhatsApp's decision, and support cannot lift it. Relink the number and the daily limit rebuilds from the start. - **A mailbox will not connect.** See [My mailbox won't connect](https://docs.warmerly.com/help/mailbox-wont-connect). ## Frequently asked questions **Can I post to social platforms from Warmerly?** No. There is no screen for it. **Which channels can I run outreach on?** Email and LinkedIn in campaigns, and WhatsApp one-to-one messages in the Inbox. **Is there a waitlist or launch date for other channels?** None is published here, so follow the [changelog](https://docs.warmerly.com/changelog) to see what ships. --- # How does Warmerly billing work? Everything about your plan and payments lives in **Settings > Billing** in [app.warmerly.com](https://app.warmerly.com/login). That page shows your current plan, its status (for example "Renews" with a date, "Trial ends" with a date, or "Past due"), and lets you change plan. The **Manage billing** button opens Stripe's secure billing portal, which is where your invoices, receipts and payment method are. For what each plan costs and includes, see [Plans and limits](https://docs.warmerly.com/plans-and-limits) or [warmerly.com/pricing](https://warmerly.com/pricing). This page explains how the billing itself behaves. ## Who can see and change billing Billing belongs to the **workspace**, and only the workspace **owner** can change it: pick or switch a plan, open Manage billing, buy credits or add-ons. Admins and members can use the workspace but get a message telling them to ask the owner. See [Team members and roles](https://docs.warmerly.com/help/team-members-and-roles). If your workspace is an Agency **client workspace**, it has no billing of its own. The Billing page says "Included in your Agency plan" and links to the Agency workspace, where everything is managed. See [Agency client workspaces](https://docs.warmerly.com/help/agency-client-workspaces). ## Where do I find my invoices and receipts? 1. Open **Settings > Billing**. 2. Click **Manage billing**. Stripe's billing portal opens. 3. Your invoice history and payment method are there. You can update your card and download invoices from the same place. You also get an email receipt for each charge. Manage billing only appears once the workspace has a paid subscription. On the Free plan there is nothing to invoice. ## How do I update my card? Click **Manage billing** in **Settings > Billing** and update the payment method in the portal. If a payment has failed, updating the card is what clears it; see [Why is my workspace locked?](https://docs.warmerly.com/help/billing-locked). ## Monthly or annual billing - **Monthly:** billed in advance every month and renews automatically until you cancel. - **Annual:** billed once a year, in advance, at a discount compared with twelve monthly payments. The exact saving is shown on the card in Settings > Billing and on the [pricing page](https://warmerly.com/pricing). If you already pay monthly, the **Switch to annual** card at the top of **Settings > Billing** moves your existing subscription to annual in one click. You are charged the annual price straight away, less a credit for the unused part of the current month. Everything on the subscription (your plan and any hosted OneMail mailboxes) moves to annual together. Limits of that switch: - There is no button to go from annual back to monthly in the app. - An approved Warmerly for Startups subscription cannot be switched while its free period or its discount is running. See [Warmerly for Startups](https://docs.warmerly.com/help/warmerly-for-startups). - If a subscription has an older add-on on it that cannot be repriced, the switch is refused with a message asking you to contact support@warmerly.com. ## Which currency am I charged in? Warmerly sells in GBP, EUR and USD. The currency a new customer is offered depends on where they are visiting from, and the checkout charges exactly the currency the page quoted. - A subscription **keeps its currency**. Plan changes, add-ons and credit packs all stay in the currency the subscription started in. - The plan picker inside the app quotes USD, monthly, until you have a subscription. To start in GBP or EUR or on an annual plan, start from [warmerly.com/pricing](https://warmerly.com/pricing). - There is no in-app switch between currencies. Ask support@warmerly.com if you need one; Warmi and support cannot change it for you inside the chat. ## What happens when I change plan? Changing plan from **Settings > Billing** (**Switch to this plan**) takes effect immediately and is prorated. - **Upgrade:** you are charged the difference for the rest of the current period. - **Downgrade:** the unused part of the higher plan becomes a credit on your billing account, set against future invoices. Credits are never paid out in cash. - **During a trial:** nothing is prorated. The plan you are on when the trial ends is the one first charged. - A plan change keeps your billing interval and currency. If a downgrade leaves you over the new plan's limits, you get a grace period to reduce usage. See [What happens if I am over my plan's limits?](https://docs.warmerly.com/help/over-plan-limits). ## Buying for a business: VAT numbers Tax is calculated by Stripe at checkout. On the card form you can choose **Buying for a business? Add your VAT number**, with an optional business name. Stripe validates the number and prints it on every invoice. An EU or UK VAT number is accepted; a number from any other country is refused with a reason shown on the form. The field is optional. ## Promo codes If you have a promo code, enter it when you add your card. Codes apply only on the terms stated with them and cannot be exchanged for cash. When a promotional period ends, the subscription renews at the standard price. An approved startup deal has its own discount and does not take a code. ## Other things that are billed separately These are not part of the plan price and are bought where you use them: - Hosted OneMail mailboxes, billed per mailbox on your subscription ([OneMail](https://docs.warmerly.com/help/onemail-mailboxes)). - LinkedIn account slots and WhatsApp number slots, monthly subscriptions bought on **Settings > Usage & limits**. - AI credit packs, one-off payments ([AI credits](https://docs.warmerly.com/help/ai-credits)). ## What support and Warmi can and cannot do They can explain what you see and where to click. They cannot change your plan, cancel, take a payment, apply a discount or refund a charge. Those are always yours to do in **Settings > Billing**, or a decision for the team by email. See the [refund and cancellation policy](https://docs.warmerly.com/help/refunds-and-cancellation-policy). ## Common problems **"I do not see Manage billing."** Either you are not the workspace owner, the workspace has no paid subscription yet (Free), or it is an Agency client workspace. Only the owner sees the button. **A Free workspace shows "Start ... trial" instead of "Switch to this plan".** A Free workspace has no subscription to move, so choosing a plan opens a card form and starts one. **"I was charged twice."** Email hello@warmerly.com within 60 days of the charge. Please contact us before your bank; the [policy](https://docs.warmerly.com/help/refunds-and-cancellation-policy) explains why. ## Related - [How do I cancel or change my plan?](https://docs.warmerly.com/help/cancel-or-change-plan) - [What happens when my trial ends?](https://docs.warmerly.com/help/trial-and-first-charge) - [Plans and limits](https://docs.warmerly.com/plans-and-limits) --- # What happens when my free trial ends? When the trial ends, your card is charged for the plan you are on and the subscription carries on as a normal paid plan, monthly or annual depending on what you chose. The first charge lands the day after the trial's last day (day 8 of a standard 7-day trial). If you cancel before then, you are not charged. You can see the exact end date in **Settings > Billing**: the status badge reads "Trial ends" followed by a date. ## How long is the trial? The trial length is shown on the button you press and on the card form, and it is what the checkout actually creates. It is normally 7 days. It is longer only in two cases: - You claimed a longer trial offer on the Warmerly website when you signed up (the offer has its own time window and is used once per account). - You were approved for [Warmerly for Startups](https://docs.warmerly.com/help/warmerly-for-startups), which has its own, longer trial. Free never needs a card and is not a trial. It does not run out. See [Plans and limits](https://docs.warmerly.com/plans-and-limits). ## Do I need a card to start a trial? Yes. A card is required to start a trial on any paid plan. Nothing is charged while the trial runs. You can add a promo code on the same card form. ## One trial per workspace Each workspace gets one trial, ever. If a workspace has already had one and you subscribe again, you are charged straight away, and the card form says "Confirm your subscription" and "charged today" instead of promising a free trial. ## What is limited during a trial? The trial is a fixed taste of the product, so it is the same size whichever plan you are trialling: - Monthly allowances (verifications, lookups, lead exports, placement tests, AI credits) are held at Starter levels, even on a Growth or Agency trial. - LinkedIn is not part of any plan or trial. Each LinkedIn account needs its own paid slot, charged straight away. See [Channel accounts](https://docs.warmerly.com/help/channel-slots). - The mailbox and campaign limits of the plan you chose do apply. The full allowances of your plan apply from the first charge. There is more detail in [Plans and limits](https://docs.warmerly.com/plans-and-limits#what-happens-when-you-hit-a-limit). ## Can I skip the trial and pay now? Yes. In the workspace setup step you can choose to subscribe now instead of taking the trial; the card is then charged immediately. Also, if the workspace already pays for hosted OneMail mailboxes and you add a plan to that subscription, the plan is charged straight away with no trial, because a trial would pause billing for the mailboxes too. The checkout tells you this before you confirm. ## What if I cancel during the trial? Cancelling during a trial (from **Settings > Billing > Manage billing**) ends the trial straight away rather than at its end date, and you are not charged. The workspace moves to the Free plan. Nothing is deleted, and you can pick a plan again whenever you want. The Billing page warns you about this before you open the portal. The same is true of a period we gave you at no charge through a 100% promo code: cancelling ends it immediately. If the workspace has more mailboxes or campaigns than Free allows, it is over Free's limits straight away and sending pauses until you reduce usage or choose a plan. A downgrade to Free gets no grace period. See [Why is my workspace locked?](https://docs.warmerly.com/help/billing-locked). ## What if I change plan during the trial? Nothing is prorated. The plan you are on when the trial ends is the one first charged. An approved startup subscription cannot be switched while its trial or discount is running. ## What about promo codes that make it free for a while? A subscription on a 100% promo code still moves from trial to a normal subscription at trial end. It is just charged nothing until the promotional months finish. The status badge on Settings > Billing shows how long the discount lasts, for example "Trial ends 12 Oct, then free until 12 Jan". When a promotional period ends, it renews at the standard price. ## Common problems **"I was charged when my trial ended."** That is the trial ending as designed: the first charge lands the day after the last trial day, for the plan you were on. To avoid it, cancel before then. See the [refund and cancellation policy](https://docs.warmerly.com/help/refunds-and-cancellation-policy) for the small set of cases where a payment is refunded. **"The card form says charged today."** Your workspace has already used its one trial, or you chose to subscribe now. ## Related - [How does Warmerly billing work?](https://docs.warmerly.com/help/how-billing-works) - [How do I cancel or change my plan?](https://docs.warmerly.com/help/cancel-or-change-plan) --- # Why is my workspace locked, or showing Payment failed? A locked workspace redirects most of the dashboard to a billing screen until the subscription is sorted out. **Nothing is deleted.** Your mailboxes, campaigns, leads and inbox are all still there. While the lock is on, Warmerly stops the automated activity: campaign sending, email warmup, LinkedIn warmup and WhatsApp sending are all paused. Campaigns are not cancelled or reset, and everything resumes by itself within a few minutes once the lock is cleared. The screen you see tells you which of these reasons applies. | What the screen says | Reason | How it clears | | --- | --- | --- | | Payment failed | The last charge on your subscription did not go through | Update your payment method | | Over your plan's limits | You are over your plan and the grace period has ended | Upgrade, or reduce usage | | Your trial ended when you cancelled | You cancelled during a trial, which ends it immediately | Pick a plan again | | (Workspace name) is in recovery until (date) | The workspace was deleted and is in its 30-day recovery window | Restore it on the Free plan (no card needed) or on a paid plan | | Your subscription isn't active | There is no active plan on the workspace | Pick a plan | A workspace that has never chosen a plan is sent to the plan picker (**Choose a plan**) instead. **Free needs no card** and is a real plan that does not expire. ## Payment failed Your last payment did not go through. Warmerly emails you, and Stripe may retry the charge. While it is outstanding the workspace is restricted and automated sending is paused. 1. On the **Payment failed** screen, click **Update payment method**. This opens Stripe's billing portal. 2. Update your card. Once the payment succeeds, the lock lifts by itself. 3. Or cancel in the portal. The workspace then drops to the Free plan instead of closing. If the payment stays unpaid, the subscription may be cancelled and the workspace moved to the Free plan, and hosted OneMail mailboxes billed on it may be suspended. A LinkedIn slot whose payment fails stops covering its account, and when the slot ends the account is disconnected. A WhatsApp slot that ends does not disconnect the number, but the workspace can then be over its limits (see [Channel accounts](https://docs.warmerly.com/help/channel-slots)). Amounts owed remain payable. Only the workspace owner can open the billing portal. If you are an admin or member, ask the owner. See [Team members and roles](https://docs.warmerly.com/help/team-members-and-roles). ## Over your plan's limits You are using more mailboxes, active campaigns or active prospects, LinkedIn accounts or WhatsApp numbers than your plan includes, and the grace period has finished. The screen lists what is over and links to where to reduce it (Accounts, Campaigns). You have two exits: - **Reduce usage** (disconnect a mailbox, pause a campaign, remove leads), then click **I've reduced my usage, check again**. Warmerly recounts straight away and lets you back in if you are inside the limits. - **Upgrade.** The screen recommends the cheapest plan your current usage fits inside and says which count drove it. LinkedIn is the exception: every plan includes zero LinkedIn accounts, and each one has its own slot subscription, so upgrading does not fix a LinkedIn-over lock. Either add a slot in **Settings > Usage & limits** or disconnect the account. Full detail, including the grace period, is in [What happens if I am over my plan's limits?](https://docs.warmerly.com/help/over-plan-limits). You can still open **Accounts**, **Campaigns** and **Settings** while locked for this reason, because those are the pages you need to fix it. ## Your subscription isn't active There is no active plan on the workspace. Pick a plan on the screen; your data and campaigns are all still there. Choosing Free needs no card. ## Your trial ended when you cancelled You cancelled while on a trial, and cancelling ends a trial straight away. Nothing was deleted. Choose a plan when you want to continue. See [What happens when my free trial ends?](https://docs.warmerly.com/help/trial-and-first-charge). ## Workspace in recovery A deleted workspace is locked for everyone until it is restored or subscribed to. The screen offers **Restore on the Free plan** above the paid plans. See [Delete or restore a workspace](https://docs.warmerly.com/help/delete-or-restore-workspace). ## What Warmi can do here Warmi is docked on the locked screen and can tell you exactly why the workspace is locked and what would clear it. It cannot unlock anything, upgrade, extend a grace period, apply a discount or take a payment. Those are yours to do on the screen. If something we broke (a bug, an outage, a checkout that would not complete) is what is keeping you locked, ask Warmi to escalate to a person. ## Common problems **"I paid but I am still locked."** After the card goes through, the plan can take a moment to switch over. The screen says "Still confirming your payment". Do not re-enter your card. Reload in a minute, or email support@warmerly.com if it does not clear. **"I reduced my usage and it is still locked."** Click **I've reduced my usage, check again**. If it still says you are over, the screen names what is still over. Something other than usage may be holding the lock, so ask Warmi. **"My campaigns are not sending but I am not locked."** Locks are not the only reason sending pauses. See [Why did my sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused). ## Related - [How does Warmerly billing work?](https://docs.warmerly.com/help/how-billing-works) - [Plans and limits](https://docs.warmerly.com/plans-and-limits#billing-lock) --- # What happens if I am over my plan's limits? You get a grace period, and **nothing is ever deleted**. While you are over a limit and inside the grace period, everything keeps running and a banner across the dashboard counts down the days. If you are still over when it ends, sending and warmup pause (campaigns stay exactly as they are) until you upgrade or reduce usage. Both fixes are equally valid. The limits themselves are on [Plans and limits](https://docs.warmerly.com/plans-and-limits). This page is about what happens when you cross one. ## Which limits can put a workspace over? These are capacity limits, meaning a live count with nothing to reset: - **Mailboxes** you connected yourself. Hosted OneMail mailboxes and the free sandbox mailbox do not use a plan mailbox slot. - **Campaigns** that are active or paused. Drafts do not count. - **Active prospects**: the distinct leads still in play across those campaigns. Leads that are completed, skipped, unsubscribed or bounced do not count. - **LinkedIn accounts** and **WhatsApp numbers**, against the slots you have paid for (and, for WhatsApp, the numbers your plan includes). Monthly allowances (verifications, lookups and so on) are different: running out of one stops that one tool until the 1st or until you buy more. See [Buy more when you run out](https://docs.warmerly.com/help/buy-more-when-you-run-out). Everything is visible in **Settings > Usage & limits**. ## How does a workspace end up over? - **A downgrade.** You moved to a smaller plan while using more than it includes. - **Growth that nobody noticed.** For example, importing leads into campaigns until the active-prospect ceiling is crossed. A nightly check spots it and starts the grace period. - **A trial or subscription ending.** The workspace falls back to Free, which is a smaller plan (see below). Adding a mailbox or launching a campaign beyond your allowance is usually refused at that moment with an explanation, and nothing is charged. The grace period is for the cases where you drifted over without a single action crossing the line. ## The grace period - When a workspace is first found over a limit, it gets **30 days** to fix it. - The dashboard shows a banner naming exactly what is over and how many days are left ("You have N days to upgrade or reduce usage before sending pauses"). You can dismiss it for the day while the grace period is still open. - The workspace owner also gets an email, "Action needed on your Warmerly plan". It is sent under the **Mailbox alerts** setting in **Settings > Email preferences**. If you have that turned off you will not get it, so rely on the banner. - If a downgrade between two paid plans caused it, the clock is set from that moment against the plan you are now on. **One case gets no grace period.** Moving to the Free plan (after cancelling or a trial ending) applies Free's limits straight away, so a workspace with more than Free allows is restricted immediately. See [Why is my workspace locked?](https://docs.warmerly.com/help/billing-locked). ## When the grace period ends Nothing is removed. The workspace is locked to the billing screen, except for **Accounts**, **Campaigns** and **Settings**, which stay open so you can fix it. While locked, campaign sending, email warmup, LinkedIn warmup and WhatsApp sending are suspended. Campaigns stay `active` and mailboxes stay connected, and they resume by themselves within a few minutes of the workspace being fixed. ## How do I get back inside the limits? 1. Open the screen or banner and see what is over (it names the resource and the count). 2. Reduce it, or upgrade: - **Mailboxes:** disconnect ones you no longer use in **Accounts**. - **Campaigns:** pause and archive campaigns you are not running in **Campaigns**. - **Active prospects:** remove leads from campaigns you are not working. - **LinkedIn or WhatsApp:** disconnect the account or number, or buy a slot in **Settings > Usage & limits**. - **Upgrade:** **Settings > Billing**, or the upgrade card in the sidebar. The billing-locked screen also recommends the cheapest plan your current usage fits into. 3. If you are locked, click **I've reduced my usage, check again**. The recount is immediate and the lock lifts on your next page load. You do not have to wait for the nightly check. If a limit is one that no plan change fixes (LinkedIn accounts are always bought as slots), the screen says so instead of selling you an upgrade that would not help. ## Can support extend my grace period? Warmi and support cannot change your plan, waive a limit or extend a grace period on request. If you are locked because of something Warmerly got wrong (a bug, an outage or a checkout that would not complete), ask Warmi to escalate it to a person. ## Common problems **"The banner says I am over but I disconnected everything."** Counts refresh when you reload. Open **Settings > Usage & limits** to see the live numbers. If one still looks wrong, ask Warmi. **"I upgraded and it is still locked."** After paying, the plan can take a moment to switch over. Reload after a minute. If it stays, see [Why is my workspace locked?](https://docs.warmerly.com/help/billing-locked). ## Related - [Delete or restore a workspace](https://docs.warmerly.com/help/delete-or-restore-workspace) - [How do I cancel or change my plan?](https://docs.warmerly.com/help/cancel-or-change-plan) --- # I ran out of verifications or lookups. Can I buy more without changing plan? For five monthly allowances, yes. You can spend AI credits from your workspace wallet on an extra block of that one thing, instead of moving to a bigger plan. The five are: - Email verifications - Email lookups - LinkedIn lookups - Lead exports - Placement tests The block is added to your account and used after that month's allowance runs out. **Blocks never expire and do not reset on the 1st.** Nothing is ever bought automatically: credits are only spent when you press a button that states the price. If you would rather move up a plan, see [How do I cancel or change my plan?](https://docs.warmerly.com/help/cancel-or-change-plan). ## How do I buy an extra block? 1. Open **Settings > Usage & limits** in [app.warmerly.com](https://app.warmerly.com/login). 2. Find the allowance you have run out of. Under its meter, once it is at 75% or more used, a line offers a block in the form "N credits adds N more verifications", with a button showing the credits. 3. Click the button. The credits come out of your wallet and the extra units are banked straight away. 4. Once you have a block banked, the same line reads "N extra verifications banked", and whether it is "in use now" or "used once this month runs out". If you do not have enough credits, buy a pack first from the **Buy more credits** section on the same page. See [AI credits](https://docs.warmerly.com/help/ai-credits). You will also see the offer in the message you get when a tool refuses because the allowance is spent, and the upgrade dialog (below) has an **Or top up with credits** link. ## What can not be topped up? - **Capacity limits** (mailboxes, active campaigns, active prospects) are a live count, not a monthly total. You fix those by reducing usage or upgrading. See [What happens if I am over my plan's limits?](https://docs.warmerly.com/help/over-plan-limits). - **LinkedIn accounts and WhatsApp numbers** are bought as slots on Settings > Usage & limits. - **AI credits** themselves. Credits are the currency; buy a pack. - **Campaign sends.** Sending is not metered on paid plans, so there is nothing to top up. ## How blocks behave - **Never expire.** A block stays on your workspace until it is used, unlike the monthly allowance, which resets on the 1st. - **Used after the month's allowance.** The month's own allowance is drawn first. The block only starts to go down once it is spent. The meter on Settings > Usage & limits shows the banked units beside the monthly figure, not folded into it. - **Whole blocks.** You buy a block up front. If it gives slightly more than you asked for, the extra is banked, not lost. - **Paid from the wallet only.** The credits used come from credits you have bought, never from your plan's included monthly credits, so topping up verifications does not use up the credits your AI features rely on. - **Only the owner.** Buying a block needs the same permission as changing the plan, so it is done by the workspace owner. - **No cash value, no refund.** Unused blocks and credits are not refunded, and they end if the workspace is permanently deleted. See the [refund and cancellation policy](https://docs.warmerly.com/help/refunds-and-cancellation-policy). - **Agency client workspaces** share one wallet with the Agency workspace. See [Agency client workspaces](https://docs.warmerly.com/help/agency-client-workspaces). The exact price in credits for each allowance is shown on the button before you press it. ## The upgrade card and upgrade dialog Warmerly offers the plan directly above yours in two places. Nothing here charges you without a click. **The sidebar card.** At the bottom left of the sidebar, above Billing, a card says what the next plan unlocks, for example "Starter unlocks (a number of) mailboxes". If any allowance is at 75% or more, the card turns amber, names the fullest one and shows its meter ("Almost out of ..." or "You're out of ..."). It has an X to hide it. It stays hidden until something changes (an allowance crosses 75% or runs out, you change plan) or 30 days pass. That choice is remembered in your browser only, so another device still shows the card. The card is not shown on the top plan, on Agency client workspaces, or to anyone who is not the workspace owner. **The dialog.** When a limit stops something you tried to do (a mailbox, campaign, allowance or full campaign list), a dialog can open offering the next plan. It waits until any dialog you are in, such as the add-mailbox wizard, has closed. Its main button is either "Try (plan) free for N days" if a trial is still available, or "Upgrade to (plan)" with the price. - If you already pay, the button changes your plan right away and charges only the prorated difference today. - If you are on Free, it opens the card form. - If you are not the owner, the dialog tells you to ask the owner rather than showing a button. - **Compare all plans** links to Settings > Billing, and **Not now** closes it. ## Common problems **"There is no top-up line under my meter."** It only appears from 75% used, and only for the five allowances above. If it never appears for one of them, that allowance may be unmetered on your plan. **"The top-up says I do not have enough credits."** Buy a pack in **Buy more credits**, then try again. **"I bought a block but the tool still says I have none."** Reload Settings > Usage & limits. The banked units show beside the monthly meter. If it still looks wrong, ask Warmi. ## Related - [AI credits](https://docs.warmerly.com/help/ai-credits) - [Plans and limits](https://docs.warmerly.com/plans-and-limits) - [Usage and quotas API](https://docs.warmerly.com/usage) --- # What are AI credits, what uses them, and how do I buy more? AI credits are the currency for the features that call an AI model on your behalf. Your plan includes a monthly amount that resets on the 1st, and you can buy packs for more. Purchased credits never expire while your workspace exists. You can see both numbers in **Settings > Usage & limits**. ## The two kinds of credit | | Monthly allowance | Purchased balance | | --- | --- | --- | | Where it comes from | Your plan | Credit packs you buy | | Resets | Yes, on the 1st. No rollover | No. Never expires while the workspace exists | | Used | First | After the allowance is spent | When something costs credits, Warmerly draws from the monthly allowance first and then from your purchased balance for the rest. If the two together are not enough, nothing is spent and the feature does not run. How big the monthly allowance is depends on your plan. See [Plans and limits](https://docs.warmerly.com/plans-and-limits). During a free trial the allowance is held at Starter level whichever plan you are trialling. ## What uses credits? - **AI-written campaign messages.** Each AI-personalised message a campaign sends costs one credit. This covers a step with **AI personalize (1 credit/message)** turned on, the `{{ai_opener}}` opening line, and AI-personalised LinkedIn messages. If nothing was generated, the credit is refunded. - **Extra blocks of monthly allowances.** Spending credits on a block of extra verifications, lookups, exports or placement tests. See [Buy more when you run out](https://docs.warmerly.com/help/buy-more-when-you-run-out). Previews you open in the campaign editor can also use a credit when they write a real opener. Sequence steps shown as "written when this actually sends" never spend a credit just for being displayed. See [AI personalisation with the AI opener](https://docs.warmerly.com/help/ai-opener). Plain sending and warmup do not use AI credits, and verification, lookups and exports draw on their own monthly allowances instead. ## Where do I see my balance? 1. Open **Settings > Usage & limits**. 2. The credits card shows **AI credit balance** (the purchased wallet) and **Monthly allowance**, with a bar showing what is used. The bar's hint says "Drawn before your balance". 3. Click **Recent activity** to see each purchase, spend and top-up with its date and amount. A top-up appears as, for example, "Extra email verifications", not as an AI message. The campaign editor also shows a credits indicator next to the AI personalize option. ## How do I buy more credits? 1. Open **Settings > Usage & limits** and find **Buy more credits**. 2. Choose a pack (small, medium or large; the medium one is marked **Most popular**). The price per credit is shown on each. 3. Click **Buy**. You are sent to a Stripe checkout and back to Settings > Billing when done. 4. Credits are added once the payment is confirmed. A card payment is instant. A bank debit is credited when it clears. Pack prices are in your workspace's currency and are on the page itself. Packs are one-off payments, not a subscription, and there is no annual version. Only the workspace owner can buy them, because it charges the workspace's card. A business can add a VAT number at checkout to get a proper invoice. ## What happens when I run out? - **A campaign step with AI personalize on** sends your own template text for that step when no credit is available, rather than nothing. - **A campaign that uses `{{ai_opener}}`** holds **all sending for that campaign** while credits are missing (the same happens if the brief is missing or the AI service is down). Leads stay queued and nothing is lost. Top up and sending resumes by itself. The reason is that an email with no opening line is worse than a delay. - **A top-up block** cannot be bought, and the button tells you why. Buying a pack fixes all three. ## Do credits expire? Can I get a refund? The monthly allowance resets and does not roll over. Purchased credits do not expire while your workspace exists, but they have no cash value, cannot be transferred to another customer and are not refunded. They end if the workspace is permanently deleted. An Agency workspace and its client workspaces share one wallet, so a pack bought on the Agency workspace works in every client. See [Agency client workspaces](https://docs.warmerly.com/help/agency-client-workspaces) and the [refund and cancellation policy](https://docs.warmerly.com/help/refunds-and-cancellation-policy). ## Common problems **"I bought a pack but my balance did not change."** Reload the page. Card payments are credited within moments. A bank debit is credited when it clears. If it does not appear, email support@warmerly.com with the receipt. **"My AI campaign stopped sending."** Check credits first, then the campaign brief. See [AI personalisation with the AI opener](https://docs.warmerly.com/help/ai-opener). ## Related - [Buy more when you run out](https://docs.warmerly.com/help/buy-more-when-you-run-out) - [How does Warmerly billing work?](https://docs.warmerly.com/help/how-billing-works) --- # How do client workspaces work, and how do I pay for a second workspace? A workspace is a separate space with its own mailboxes, campaigns and inbox, kept apart from your other workspaces. How a **second** workspace is paid for depends on your plan: - **You own a workspace on the Agency plan:** a new workspace becomes a **client workspace** inside your Agency plan. No card, no setup questions, and it shares the Agency workspace's allowances. - **Any other plan (including Free):** a new workspace is paid for on its own. You choose a paid plan for it. Free is never offered for an extra workspace. Whether Agency includes client workspaces, and how many, is on the [pricing page](https://warmerly.com/pricing) and in [Plans and limits](https://docs.warmerly.com/plans-and-limits). ## How do I create a workspace? 1. Open **Settings > Workspaces** and click **New workspace**. You can also use **Manage workspaces** in the workspace switcher in the sidebar. 2. Type a **Workspace name**. 3. What happens next depends on your plan: - Agency owner: the button reads **Create workspace** and you are done. The page says "Included in your Agency plan". - Anyone else: the button reads **Continue to choose a plan**, and you pick a plan and add a card for the new workspace. You do not have to answer the setup questions again. Your earlier answers, sender name and postal address are copied and can be edited later. The page also offers **Upgrade to Agency** if you would rather run everything under one plan. You can switch between workspaces from the switcher or from **Settings > Workspaces** with **Switch**. ## What do client workspaces share? Everything about the plan belongs to the Agency workspace, and the client workspaces count against it together: - **Capacity limits**, added up across the whole family: mailboxes, active campaigns, active prospects, LinkedIn accounts and WhatsApp numbers. - **Monthly allowances** (verifications, lookups, exports, placement tests, AI credits): the Agency plan's limits. - **The AI credit wallet.** A pack bought on the Agency workspace is usable in every client workspace. - **The grace period and any lock.** If the family goes over the plan, the Agency workspace's billing state applies to all of it. See [What happens if I am over my plan's limits?](https://docs.warmerly.com/help/over-plan-limits). Each client workspace still has its own mailboxes, campaigns, leads, inbox, do-not-contact list and team. ## What can I not do inside a client workspace? A client workspace has no subscription of its own, so billing actions are refused there: switching plan, opening Manage billing, entering a promo code, buying credits, or buying LinkedIn or WhatsApp slots. **Settings > Billing** in a client workspace says "Included in your Agency plan" and has a button to go to the Agency workspace's billing, where everything is done. **OneMail hosted mailboxes cannot be ordered inside a client workspace.** Order them on the Agency workspace. See [OneMail](https://docs.warmerly.com/help/onemail-mailboxes). ## What if I delete a client workspace? Your bill does not change. It locks now, is kept for 30 days, and can be restored any time before then. See [Delete or restore a workspace](https://docs.warmerly.com/help/delete-or-restore-workspace). ## What happens when Agency ends? If the Agency plan is downgraded, lapses or its workspace is deleted, its clients are no longer covered. Nothing is swept or deleted. Each client workspace simply has no plan of its own, and its owner is sent to the plan picker for that workspace. A plan chosen there belongs to that workspace from then on. If the Agency workspace comes back to a live Agency plan before you pick, the clients rejoin the pool automatically. ## Paying for a second workspace on a non-Agency plan 1. Create the workspace as above and choose a paid plan. It gets the same trial rules as any subscription: see [What happens when my free trial ends?](https://docs.warmerly.com/help/trial-and-first-charge). 2. That workspace has its own subscription, invoices and Manage billing. Allowances are not pooled with your first workspace's plan. 3. Only one unfinished workspace of this kind can exist at a time. Creating another reuses it under the new name. An unfinished workspace with no plan and nothing paid is removed straight away if you delete it. Monthly allowances that are counted per person (verifications, lookups, exports and so on) follow you across the workspaces you own, so check **Settings > Usage & limits** in the workspace you are working in. ## Common problems **"I do not see Free when I create a second workspace."** By design. An extra workspace needs a paid plan, or the Agency plan that includes client workspaces. **"My client workspace shows Included in your Agency plan and I cannot buy credits."** Switch to the Agency workspace and buy there. The wallet is shared. **"My client workspace asks me to pick a plan."** The Agency plan it belonged to has ended. Choose a plan for it, or restore the Agency plan. ## Related - [Team members and roles](https://docs.warmerly.com/help/team-members-and-roles) - [How does Warmerly billing work?](https://docs.warmerly.com/help/how-billing-works) --- # How do I delete a workspace, and can I get it back? Open **Settings > Workspaces**, find the workspace and click **Delete**. A confirmation says exactly what will happen to that workspace. A deleted workspace is **kept for 30 days**, and the owner can restore it at any time in that window with no card. After the 30 days it is permanently deleted and cannot be recovered. Deleting is done in one place, **Settings > Workspaces**. The **Team** page links there. **Only the workspace owner** can delete or restore a workspace. ## What happens when I delete, by type of workspace | Workspace | What Delete does | | --- | --- | | On the Free plan | Locked now. Kept for 30 days, restorable. | | On a paid plan with its own subscription | The plan stops renewing. The workspace keeps working until the end of the period you have already paid for (no refund), then it is locked and kept for 30 days. | | An Agency client workspace | Locked now, kept for 30 days. Your bill does not change. | | Extra workspace you never finished setting up (no plan chosen, nothing paid) | Removed straight away, nothing to restore. | If you delete an Agency workspace that has client workspaces, they share its plan and lock when it ends. The confirmation says how many. Deleting a paid workspace stops the subscription renewing. It does not refund the current period. See the [refund and cancellation policy](https://docs.warmerly.com/help/refunds-and-cancellation-policy). After a delete that locks the workspace immediately, Warmerly switches you to your oldest other active workspace, so you do not land on the recovery screen of the workspace you just deleted. ## What does a deleted workspace look like? - In **Settings > Workspaces** the row reads "Deleted · kept until (date)" with a **Restore** button. - If you open it, the billing screen says the workspace "is in recovery until (date)" and "Nothing has been deleted yet. Everything is still here." - Automated sending, warmup and other activity stop while it is locked. - The owner gets reminder emails during the 30 days (around days 1, 7, 21 and 28) so it is not forgotten. - A paid workspace scheduled for deletion but still inside its paid period shows a "This workspace is scheduled for deletion" notice on the **Team** page and a **Keep it** button in **Settings > Workspaces**. ## How do I restore a workspace? 1. Open **Settings > Workspaces** and click **Restore** on the deleted workspace. If it is a paid workspace still inside the period you paid for, the button reads **Keep it**. 2. Or, on the locked screen, click **Restore on the Free plan**, or pick a paid plan. Restoring needs no card. Where the workspace ends up: - **Deletion still scheduled** (paid, not yet locked): the cancellation is switched off and the subscription carries on as before. - **Already locked, was a client workspace:** it goes back into its Agency pool, if that Agency workspace still has a live Agency plan. - **Already locked, still has its own subscription:** it keeps it. - **Otherwise:** it comes back on the **Free** plan. If it has more mailboxes or campaigns than Free allows, sending stays paused until you reduce usage or choose a paid plan. See [What happens if I am over my plan's limits?](https://docs.warmerly.com/help/over-plan-limits). If you subscribe again on a workspace that is in recovery, the deletion is cancelled and the workspace comes back whole. ## What happens to my data? For the 30 days nothing is deleted. After that the workspace is permanently deleted: its mailboxes, campaigns, contacts, inbox and settings. Purchased credits and quota blocks end with it. Tax and accounting records are kept by law, and some records (such as opted-out addresses) are kept so nobody is contacted again. Details are in [What happens to my data if I cancel or delete?](https://docs.warmerly.com/help/data-after-cancelling-or-deleting). ## Common problems **"I cannot see the Delete button."** Only the owner can delete. Admins and members do not get it. See [Team members and roles](https://docs.warmerly.com/help/team-members-and-roles). **"I deleted the wrong workspace."** Restore it within 30 days from **Settings > Workspaces**. Later than that it cannot be recovered. **"I deleted a workspace but I am still being charged."** A paid workspace keeps its subscription until the end of the paid period, then stops. It is not refunded for the rest of it. If the plan still renews after the end date, email support@warmerly.com. **"Can I delete my account, not just a workspace?"** Workspace deletion is what the app offers. To have your personal data erased, use a [privacy request](https://docs.warmerly.com/help/privacy-requests). ## Related - [How do client workspaces work?](https://docs.warmerly.com/help/agency-client-workspaces) - [How do I cancel or change my plan?](https://docs.warmerly.com/help/cancel-or-change-plan) --- # How do I invite teammates, and what can each role do? Open **Settings > Team**, type your teammate's **Email address**, choose a role (**Admin** or **Member**) and click **Send invite**. They get an email with a link. Once they accept, they appear in the members list. Roles belong to one workspace, so someone can be an admin in one workspace and a member in another. ## What each role can do | | Owner | Admin | Member | | --- | --- | --- | --- | | Use the workspace (campaigns, inbox, mailboxes, leads) | Yes | Yes | Yes | | See the members list | Yes | Yes | Yes | | Rename the workspace, change branding and sender details | Yes | Yes | No | | Invite, remove people and change roles | Yes | Yes | No | | Change plan, open Manage billing, buy credits or add-ons | Yes | No | No | | Delete or restore the workspace | Yes | No | No | The Team page describes it in one line: "Owner: full control, including deleting the workspace. Admin: can invite, remove, and manage the team. Member: can use the workspace but not manage the team." A few finer rules: - Only an owner can give someone the Owner role, and only an owner can remove or change another owner. An admin cannot. - Billing is owner-only on purpose, because it spends the workspace's card. If an admin or member hits a limit, the upgrade dialog tells them to ask the owner. - Anyone in the workspace can open its **Audit log**. See [Audit log](https://docs.warmerly.com/help/audit-log). ## How do invites work? 1. On **Settings > Team**, enter the email, pick **Admin** or **Member**, click **Send invite**. 2. The person receives an email titled "You've been invited to (workspace) on Warmerly" with a link. 3. They open the link, sign in or create an account with **the same email address the invite was sent to**, and click **Accept invite**. If they sign in with a different address, they see "This invite was sent to a different email address." 4. The invite is valid for **7 days**. After that the link stops working. Pending invites are listed on the Team page. Click **Revoke invite** ("The invite link will stop working") to cancel one. Inviting the same address again replaces the earlier pending invite. You cannot invite someone who is already a member. If the email does not arrive, ask them to check spam, then revoke and send again. ## How do I change someone's role or remove them? In the members list, use the role selector on their row (Admin or Member) or click **Remove member** ("They will lose access to this workspace"). Removing a person also revokes any AI app connections they had made to your workspace. See [Connected AI apps](https://docs.warmerly.com/help/manage-connected-ai-apps). ## How do I transfer ownership? Set another member's role to Owner in the members list. A confirmation says "This person will become the new owner. You will become an admin instead, and you can't undo this yourself." The new owner can change it back only by doing the same to you. ## Can I leave a workspace? Yes, from the Team page: **Leave workspace** ("You will lose access until you are invited again"). An owner cannot leave. Transfer ownership first, or delete the workspace. See [Delete or restore a workspace](https://docs.warmerly.com/help/delete-or-restore-workspace). ## The rest of the Team page Above the members list, **Settings > Team** also holds: - **Workspace:** the workspace name. - **Business name** and **Postal address:** optional. They are added to the footer of every campaign email you send. Anti-spam law in some countries (CAN-SPAM in the US, CASL in Canada) asks for a real postal address in commercial email. Campaigns send either way. - **Branding:** upload a logo, shown at the bottom of the dashboard sidebar. **Remove** takes it off again. Changes here use a save bar at the bottom of the page. ## Does adding people cost extra? Plans are described per workspace, not per person, and the Team page shows no per-seat charge. Your allowances (mailboxes, campaigns, verifications and so on) are shared by the whole workspace. See [Plans and limits](https://docs.warmerly.com/plans-and-limits). ## Common problems **"My teammate cannot see Billing."** Only the owner manages billing. An admin can ask the owner to make changes, or the owner can transfer ownership. **"The invite says it was sent to a different email address."** Sign in with the exact address that was invited, or ask an admin to invite the address you actually use. **"The invite link says it is no longer valid."** It expired after 7 days or was revoked. Ask for a new one. ## Related - [Audit log](https://docs.warmerly.com/help/audit-log) - [Sign in and account security](https://docs.warmerly.com/help/sign-in-and-security) --- # What is the audit log and what does it show? The audit log is a read-only list of recent things that happened in your workspace: who invited someone, who connected or disconnected a mailbox, when the plan changed, when an API key was created. Open it at **Settings > Audit log** ("Recent activity for your team"). It answers "who changed this, and when?" after the fact. It does not undo anything and there is nothing to configure. ## What are the columns? | Column | What it means | | --- | --- | | **When** | The date and time of the event. | | **Actor** | Who did it. It is shown as an account ID for now, not a name. Your own ID appears on your own actions. | | **Action** | What happened, for example "member.invited" or "billing.plan_changed". | | **Target** | The item it affected, shown as its type and an ID, for example a workspace invite, a mailbox or an API key. | Newest events are first. If nothing has happened yet, the page says "No activity yet". ## What kinds of events are recorded? The log covers workspace-level actions. The main groups are: - **Team:** member invited, member removed, role changed. - **Workspace:** created, deletion scheduled, restored, deleted. - **Mailboxes and channels:** account connected or disconnected, transferred to another workspace, sending settings changed on a channel account, a ready-warmed OneMail mailbox claimed. - **Billing:** checkout completed, plan changed or selected, subscription upgraded or downgraded, annual switch, cancellation scheduled, subscription ended, invoice paid or payment failed. - **API keys and webhooks:** created or revoked. - **Do not contact list:** addresses added or removed. - **Connected AI apps:** an app being connected or revoked, and actions taken through one, such as creating or launching a campaign, drafting or sending a reply, or changing a campaign's settings. See [Connected AI apps](https://docs.warmerly.com/help/manage-connected-ai-apps). The exact list can grow as features are added, so treat the examples as representative rather than complete. ## What is not in it? - **Sign-ins are not listed.** Sign-in events are recorded for security but are not tied to a workspace, so they do not appear here. - **Everyday product use** (opening pages, editing drafts, ordinary campaign sending) is not an audit event. ## How much history does it keep? The page shows the latest **200 events** for the active workspace. There is no search, filter or export on the page. Older events are not paged in from the page. Longer retention for security and audit logs is described in our [privacy policy](https://warmerly.com/privacy) (section on data retention). ## Who can see it? Anyone who can open your workspace can open its audit log, because it is built for a team to see what its own people have done. It is per workspace: each workspace shows only its own events. To see another workspace's log, switch to it first. The API cannot read the audit log. It is only available to signed-in dashboard users. ## Common problems **"The Actor column shows a long ID instead of a name."** Known limitation, and the page says names are being worked on. The ID is the person's account ID. Your own actions carry your own ID, which is a way to recognise yours. **"Something I did is missing."** It may not be an audited action (see above), or it happened in another workspace, or it is older than the latest 200 events. **"I need a longer or exportable log."** The app does not offer one. Email support@warmerly.com with what you need it for. ## Related - [Team members and roles](https://docs.warmerly.com/help/team-members-and-roles) - [Sign in and account security](https://docs.warmerly.com/help/sign-in-and-security) --- # How do I sign in, change my password or email, and secure my account? You can sign in to [app.warmerly.com](https://app.warmerly.com/login) with your email and password, or with **Google** or **Microsoft**. Your name, password and login email are in **Settings > Profile**. This page covers only what exists today; anything not listed here is not a setting you can change. ## How do I sign in? - **Email and password:** enter them on the sign-in page and click **Sign in**. The address must be verified first. If it is not, you see "Please verify your email address before signing in" with **Resend verification email**. Verification links last 24 hours. - **Google or Microsoft:** use the matching button on the sign-in page. Your Google photo is used as your avatar automatically, and you can upload a different one. After too many wrong attempts, sign-in is blocked for a short while and you are asked to try again later. This applies per email address and per network. A signed-in session lasts up to 30 days on that browser. Signing out ends it on that browser. ## How do I change my password? 1. Open **Settings > Profile**. 2. In the password section, enter your **Current password**, your **New password** and **Confirm new password**. 3. Click **Update password**. The new password must be at least 8 characters. It is also checked against lists of passwords known to be leaked; only a short fragment of a fingerprint of it is ever sent for the check, never the password itself. A leaked password is refused. **Changing your password signs out every other session** (other browsers, and the Android app) but keeps the one you are using. That is the standard advice after a suspected compromise, and it works. If you signed up with Google or Microsoft you may not have a Warmerly password at all. The password form needs an existing one to confirm it is you. ## I forgot my password On the sign-in page, click **Forgot password?** under the password field (or go to [app.warmerly.com/forgot-password](https://app.warmerly.com/forgot-password)), enter your email address and click **Send reset link**. The page always shows the same message, whether or not that address has an account, so it cannot be used to find out who is registered. If the address has an account, we email a **Reset password** link. It expires after 24 hours and works once. Asking for a new link cancels the previous one. Open the link, enter a **New password** and **Confirm new password**, and click **Set new password**. The same rules apply as when you change it in Settings: at least 8 characters, and a password found in known leaks is refused. **Resetting your password signs you out everywhere**, including other browsers and the Android app. You are then sent to the sign-in page to use the new password. If the link says it has expired or was already used, request a new one from the same page. Too many requests in a short time are refused for a while, so wait a minute and try again. If you use Google or Microsoft sign-in, use that button instead. Warmi cannot reset a password for you. ## How do I change my login email? 1. Open **Settings > Profile** and find **Change email**. 2. Enter the **New email** and your **Current password**, then click **Send code**. 3. Check the new address's inbox for a **Verification code**, enter it and click **Confirm**. The code is valid for 15 minutes and you get a limited number of tries. After that, request a new code. You will see specific messages if the email is already used by another account, the password is wrong, or the code is wrong or expired. Your login email is separate from your display name and does not change anything else on your account, such as your mailboxes or billing. ## Is two-factor authentication available? Not at the moment. There is no two-factor option in Settings > Profile. What protects your account today: a long, unique password, sign-in through a provider that you have secured with its own two-step verification (Google or Microsoft), and the session and audit features below. ## What other security features are there? - **Sessions are revocable.** Each sign-in is a session on Warmerly's side. Changing your password and signing out end sessions properly, so a copied cookie stops working. - **API keys** are shown once and stored only in a scrambled form. Manage them under **Settings > Platform API keys** (an Agency plan feature). See [How do I use Warmerly with an API?](https://docs.warmerly.com/help/use-the-api). - **Connected apps:** see and revoke every AI app connected to your workspace under **Settings > Connected apps**. See [Connected AI apps](https://docs.warmerly.com/help/manage-connected-ai-apps). - **Webhooks** are under **Settings > Webhooks**. See [Webhooks](https://docs.warmerly.com/webhooks). - **Audit log:** **Settings > Audit log** lists recent workspace activity. See [Audit log](https://docs.warmerly.com/help/audit-log). - **Roles:** only owners can change billing or delete a workspace. See [Team members and roles](https://docs.warmerly.com/help/team-members-and-roles). - **Mailbox passwords and tokens** are deleted immediately when you disconnect a mailbox. ## Common problems **"Invalid email or password."** Check the address and try again. If you signed up with Google or Microsoft, use that button. **"This account has been suspended."** See [My account is suspended](https://docs.warmerly.com/help/account-suspended). **"I never got the verification email."** Check spam, then click **Resend verification email**. You can only ask again after about a minute. **"I think someone else has access."** Change your password now (that signs out other sessions), revoke unknown apps and API keys, review the Audit log and email support@warmerly.com. ## Related - [Privacy requests](https://docs.warmerly.com/help/privacy-requests) - [Email preferences](https://docs.warmerly.com/help/email-preferences) --- # How do I choose which emails Warmerly sends me? Open **Settings > Email preferences** ("Choose which emails Warmerly sends you"). There are four switches. Each saves as soon as you flip it and confirms with "You'll receive these emails" or "You won't receive these emails". The preferences belong to **you**, not to the workspace, so they apply across every workspace you use. ## The four switches | Switch | What it controls | | --- | --- | | **Mailbox alerts** | Reputation drops, DNS (SPF, DKIM, DMARC) changes and disconnected mailboxes. Bundled into at most one digest per 24 hours. | | **Lead alerts** | New replies that Warmerly AI identifies as leads. Bundled into at most one digest per 24 hours. | | **Setup tips & check-ins** | Occasional guidance while you get set up, plus milestone check-ins and referral rewards. Stops once you turn it off. | | **Product news & offers** | New features, deliverability guides and the occasional offer. Never more than a few a month. | ## What is always sent? Under **Always sent**, the page lists mail that keeps your account working and cannot be turned off: - Sign-in, email verification and password resets - Billing receipts, failed payments and plan changes - Workspace invitations and replies to your support requests If you turn every switch off, you still get these. That is deliberate: a missed failed-payment notice or invitation would cost you more than a stray tip email. ## Which switch controls the email I got? - **"Action needed on your Warmerly plan"** and **"Your Warmerly sending has paused"**, the notices about being over your plan's limits, follow **Mailbox alerts**. If you have it off, you will not get those, so watch for the countdown banner in the dashboard instead. See [What happens if I am over my plan's limits?](https://docs.warmerly.com/help/over-plan-limits). - **Referral reward emails** follow **Setup tips & check-ins**. See [The referral programme](https://docs.warmerly.com/help/referral-programme). - **Reply and lead notifications** follow **Lead alerts**. - **Warmerly news, launches and offers** follow **Product news & offers**. These emails also have an unsubscribe link in the footer, which does the same as the switch. ## Does this affect my campaigns' emails or my recipients? No. These are emails Warmerly sends to **you**. Your campaigns' emails to your leads, and their unsubscribe handling, are separate. See [Suppression](https://docs.warmerly.com/suppression) for the do-not-contact list that campaigns never send to. ## Common problems **"I turned alerts off but still got an email."** Check what it was. Billing receipts, failed payments, sign-in and invitation mail are always sent. So are replies to support requests. **"I am not getting alerts and I want them."** Turn **Mailbox alerts** or **Lead alerts** on. Check your spam folder for mail from Warmerly. Digests arrive at most once per 24 hours, so a single problem will not send repeated emails. **"I unsubscribed from a marketing email and now want it back."** Turn **Product news & offers** back on here. **"I want to change the address these go to."** Change your login email in **Settings > Profile**. See [Sign in and account security](https://docs.warmerly.com/help/sign-in-and-security). ## Related - [Sign in and account security](https://docs.warmerly.com/help/sign-in-and-security) - [How do I use the Warmerly Android app?](https://docs.warmerly.com/help/android-app) --- # How does the Warmerly referral programme work? Every account has its own referral link. When someone signs up through it and pays their first invoice, **you both get one month of Starter as account credit**. The credit comes off your next invoice automatically. It is credit, never cash. The public terms are at [warmerly.com/referrals](https://warmerly.com/referrals). The reward amount is worked out from the current Starter price and is shown on that page and in the app. ## Where do I find my link? 1. Open **Settings > Refer a friend** in [app.warmerly.com](https://app.warmerly.com/login). It is also a **Refer a friend** row at the bottom of the sidebar. 2. Your link is shown with a copy button, and **Post on X**, **Share on LinkedIn** and **Email a friend** buttons prefill a message for you. 3. Below it, **Your referrals** shows how many people **Signed up**, how many **Became paying**, and the credit earned, with a list of the people you referred (their emails are partly hidden) marked "Signed up" or "Paying". Links look like warmerly.com/r/(your code). Your code is created the first time you open the page. ## How does someone become a referral? 1. They open your link. It takes them to the Warmerly register page with your code attached. No cookie is set, so there is nothing to accept. 2. They create an account on that page, with email, Google or Microsoft. A "You were referred" notice appears on the form. 3. They start paying on a paid plan. Only the register page counts. Someone who opens your link and then signs up from a different page, or in the Android app, is not attributed to you. Ask them to sign up straight from your link. ## When do I get the credit? When the person you referred pays their **first invoice with money on it**. Then: - You each get one month of Starter as account credit, applied to your next invoice(s) automatically. - A free trial does not count. An invoice fully covered by a 100%-off promo code does not count either. - **If you are on Free with no card on file,** your credit waits and is applied when you start a paid plan. - You get a "referral reward" email, which follows the **Setup tips & check-ins** switch in [Email preferences](https://docs.warmerly.com/help/email-preferences). Occasionally the credit is applied a little after the payment, because it is finalised in a follow-up step. If you skipped the trial and paid at once, it can land on your second invoice rather than your first. ## The rules - Only **new accounts** can be referred, and referring yourself does not count. - The link is attached at signup and cannot be changed afterwards. - There is a cap on how many referral credits you can earn in any rolling 12 months. The current cap is on the [referral page](https://warmerly.com/referrals). - Credit is not cash, cannot be withdrawn and is used up by your future invoices. - Warmerly can withhold credit for referrals that are clearly not genuine, such as one person opening accounts to refer themselves. There is no other automatic fraud check, but a referral only earns credit when the person actually pays. ## Common problems **"My friend signed up but I got nothing."** Check the **Your referrals** list on **Settings > Refer a friend**. If they show "Signed up", they have not paid yet. If they are not on the list at all, they did not sign up from your link. If they show "Paying" and there is no credit, email support@warmerly.com. **"My friend is not on my list."** They probably signed up through another page or the Android app. Referrals are only captured on the register page. **"Can I get the reward as cash or a discount code?"** No. It is account credit only. **"I am a Free user. What do I do with the credit?"** It waits until you start a paid plan. ## Related - [How does Warmerly billing work?](https://docs.warmerly.com/help/how-billing-works) - [Warmerly for Startups](https://docs.warmerly.com/help/warmerly-for-startups) --- # How do I apply for and activate Warmerly for Startups? Warmerly for Startups is a programme for early-stage companies doing their own outreach. An approved startup gets the **Agency plan** on a long free trial, then a discounted price for a set number of months, then the normal Agency price. Apply at [warmerly.com/startups](https://warmerly.com/startups). **The current terms, price, eligibility limits and dates are on that page**, and the FAQ section of these docs; this page explains the process and the rules once you are in. ## Steps 1. **Apply.** Go to [warmerly.com/startups](https://warmerly.com/startups) and fill in the form (about two minutes). If you are signed in, the application attaches to your current workspace. If not, you are sent to create an account and it attaches when you do. 2. **Wait for review.** A person reviews every application, looking at your website, when the company started and what you plan to send. We may ask a follow-up question by email. Approval or decline is one email either way. Lead-generation agencies and resellers are not eligible; the programme is for startups doing their own outreach. 3. **Activate.** The approval email links to **Settings > Billing** on the approved workspace. A card at the top says "Warmerly for Startups is approved for (your company)" and has an **Activate Agency** button that also states the number of free days. Click it and add a card. There is no code to enter. 4. **Use it.** The subscription is an ordinary Agency subscription on a long trial. You get the full Agency allowances from day one, not a cut-down trial. A card is needed to activate, like any trial. Nothing is charged during the free period and you can cancel before it ends. ## What happens after the free period? The discount is attached to the subscription shortly before the free period ends, so the discounted months start with your first invoice. After the discounted months, it renews at the normal Agency price. You can move to a smaller plan or to Free at any time once the discount has finished. The exact number of free months, the discount and its length are on [warmerly.com/startups](https://warmerly.com/startups). ## Rules while it runs - **Cancelling during the free period ends it straight away**, as with any trial. You are not charged, and the discount is never attached to a cancelled subscription. See [What happens when my free trial ends?](https://docs.warmerly.com/help/trial-and-first-charge). - **You cannot switch plan** while the startup subscription is in its free period or still has the discount running. The Billing page will say to contact support. Once the discounted months are over, it switches like any other subscription. - **Add-ons follow the normal rules.** Anything you add during the free period (such as hosted OneMail mailboxes) is not invoiced until the free period ends, and then bills at its normal price. The discount covers the Agency plan only. - **No promo codes stack.** The startup deal carries its own discount. - **One application at a time** per workspace. A declined application lets you apply again. - **Approvals do not expire,** but while an approval is waiting on a workspace, you cannot start a different paid plan there. The checkout points you to the activation card. Choose **Start on Free for now** if you want to wait; that does not use up your approval. - **Agency client workspaces** cannot activate the deal on their own. Activate it on the Agency workspace itself. ## Already paying for a plan? If the approved workspace already has a live paid subscription, the deal needs a new one, so the activation button is refused. Reply to the approval email and we will move it over by hand. ## Common problems **"I was approved but I do not see the activation card."** Check that you are on the workspace you applied with. The link in the approval email switches to it. Then open **Settings > Billing**. **"It says we could not activate on this workspace."** Your card was saved but nothing was set up and nothing was charged. Email support@warmerly.com or reply to your approval email. The team is notified as well. **"I cannot change plan."** See the rules above. Ask support if you need a change during the free period. **"Can I use a promo code as well?"** No. ## Longer trials from the website Separate from this programme, a signup offer on the Warmerly website can give a longer trial than the standard one on any paid plan. It must be claimed when you sign up, is used once per account and has its own time window. The trial length is always shown on the button before you confirm. See [What happens when my free trial ends?](https://docs.warmerly.com/help/trial-and-first-charge). ## Related - [Frequently asked questions: plans and billing](https://docs.warmerly.com/faq#plans-and-billing) - [How does Warmerly billing work?](https://docs.warmerly.com/help/how-billing-works) --- # What is Warmerly's refund and cancellation policy? In short: the Free plan cannot be charged, paid plans start with a free trial so you can decide before paying, **payments already taken are not refunded** except in a few named cases, and cancelling stops future renewals while you keep access to the end of the period you paid for. This page is a summary written to help you find things. The binding wording is the [Refund & Cancellation Policy](https://warmerly.com/refunds) and the [Terms of Service](https://warmerly.com/terms) (mainly the sections on plans, billing and guarantees). If this page and those ever differ, they win. Support and Warmi can explain the policy but cannot grant a refund or change a plan; refunds are a decision for the team. ## The Free plan Free needs no card, has no time limit and is not a trial. Because no payment method is held, there is nothing to cancel and nothing to refund. Moving to a paid plan, or buying an add-on such as a hosted mailbox, is the only step that asks for a card. ## Paid plans and the trial - A paid plan normally starts with a free trial, and a card is required. Nothing is charged during it. The first charge is the day after the trial ends. See [What happens when my free trial ends?](https://docs.warmerly.com/help/trial-and-first-charge). - Cancelling **before that first charge** means you are not billed at all. - The trial is available once per workspace. A second subscription is charged straight away. ## Renewals and price changes - Plans are billed monthly or annually, in advance, and renew automatically until you cancel. Add-on subscriptions renew the same way. - Each renewal is charged to the card on file at the price then in effect. At least 30 days' notice is given by email before a price increase applies to your renewal. - You get an email receipt for each charge. Invoices, receipts and your payment method are under **Manage billing** in **Settings > Billing**. ## Plan changes Upgrades and downgrades take effect immediately and are prorated. An upgrade adds the difference for the rest of the period to your next invoice. A downgrade turns the unused part into a credit on your billing account. That credit is set against future invoices, is never paid out in cash, and any credit left when your subscription ends is not refunded. See [How does Warmerly billing work?](https://docs.warmerly.com/help/how-billing-works). ## Refunds: what is and is not refunded **Not refunded:** payments already taken. That covers monthly and annual plan charges (including renewals you forgot to cancel), prorated charges, and add-ons: hosted mailboxes, LinkedIn and WhatsApp slots, credit packs and the credits spent on quota blocks. Unused allowances, credits and blocks have no cash value. **LinkedIn accounts are never refunded.** A LinkedIn slot, and a 3-account or 5-account pack, is charged immediately with no trial, and none of the cases below applies to it. Cancelling stops the next renewal and the accounts keep working until the end of the period already paid for. This does not affect any right the law gives you, for example as a consumer (section 12.5 of the Terms). The point to decide is **before the first charge**. The trial and the Free plan exist so you can evaluate the product without paying, which is why there is no money-back window afterwards. **Refunded** in these cases: - We charged you in error, for example twice for the same thing, or after you had validly cancelled. - We end your account for a reason other than your breach: prepaid fees for the period after it ends are refunded. - A mailbox qualifies under the **inbox guarantee** in the Terms (section 18A, [warmerly.com/terms#guarantees](https://warmerly.com/terms#guarantees)): that month's plan fee is refunded. Claims go to support@warmerly.com within the window stated in the Terms. - The law requires it, including your rights as a consumer (below). Any other refund or credit is at Warmerly's discretion, applies only to the case it was given for and sets no precedent. Approved refunds go back to the original payment method; how long they take to appear is up to your bank. ## How to cancel - **Your plan:** **Settings > Billing**, click **Manage billing**, cancel in the billing portal. Only the workspace owner can. No contract, no minimum term, no cancellation fee. See [How do I cancel or change my plan?](https://docs.warmerly.com/help/cancel-or-change-plan). - **Slots and hosted mailboxes:** remove them from the part of the app where you manage them. Cancel a LinkedIn or WhatsApp slot with the **Cancel** button on its row in **Settings > Usage & limits**. It takes effect at the end of the period already paid for. A LinkedIn account using it is then disconnected. A WhatsApp number is not disconnected. Removing a hosted mailbox ends the address. - **Agency client workspaces** have no billing of their own. Cancel from the Agency workspace. - **Cannot cancel in the app?** Email hello@warmerly.com from the account owner's address before your renewal date and it will be cancelled for you. - **Deleting a workspace** with its own paid subscription stops it renewing but does not refund the current period. ## What happens when a paid plan ends Cancellation takes effect at the end of the current billing cycle and you keep access until then. The workspace then moves to the Free plan rather than being closed, and your data is not deleted by cancelling. If it is over Free's limits, it is restricted straight away until you reduce usage or subscribe again. Cancelling during a trial, or during a promotional period at no charge, ends access straight away. See [What happens to my data if I cancel or delete?](https://docs.warmerly.com/help/data-after-cancelling-or-deleting). ## Failed payments If a payment fails you are emailed and Stripe may retry. While it is outstanding the workspace is restricted and automated sending is paused. Update the card under **Manage billing** to clear it. If it stays unpaid, the subscription may be cancelled and the workspace moved to Free. See [Why is my workspace locked?](https://docs.warmerly.com/help/billing-locked). ## If you are a consumer Warmerly is sold for business use. If you are nonetheless contracting as a consumer, you have a statutory right to cancel within 14 days of subscribing, and your consumer rights stand regardless of the rest of the policy. To use that right, email hello@warmerly.com with a clear statement that you are cancelling. The full conditions are in section 10 of the [Refund & Cancellation Policy](https://warmerly.com/refunds). ## Billing disputes If you think you were charged in error, email hello@warmerly.com within 60 days of the charge. Please contact us before your bank. Opening a chargeback for a charge you owe breaches the Terms, and the account may be suspended while it is open. ## Related - [How does Warmerly billing work?](https://docs.warmerly.com/help/how-billing-works) - [Warmerly Terms of Service](https://warmerly.com/terms) --- # What happens to my data if I cancel or delete my workspace? **Cancelling does not delete anything.** The workspace moves to the Free plan and your mailboxes, campaigns, leads and inbox are all kept. **Deleting a workspace** is different: it is kept for 30 days so you can restore it, then permanently deleted. The binding wording on retention is in the [Privacy Policy](https://warmerly.com/privacy) (section 8, Data retention). This page explains it in terms of what you do in the app. ## If I cancel my subscription - On a paid plan you keep everything until the end of the period you paid for. Then the workspace moves to **Free**. It is not closed. - Nothing is deleted. Your mailboxes, campaigns, leads and inbox remain. - If you have more than Free allows (mailboxes, active campaigns), sending and warmup pause straight away until you reduce usage or pick a paid plan. Nothing is removed to make room. See [What happens if I am over my plan's limits?](https://docs.warmerly.com/help/over-plan-limits). - **During a trial**, cancelling ends the trial immediately and nothing is deleted either. - **Agency:** if the Agency plan ends, its client workspaces are no longer covered. Nothing is deleted, and each one needs a plan of its own to continue. See [Agency client workspaces](https://docs.warmerly.com/help/agency-client-workspaces). ## If I delete a workspace - The workspace is locked and kept for **30 days**. You can restore it at any time in that window, without a card. See [Delete or restore a workspace](https://docs.warmerly.com/help/delete-or-restore-workspace). - A paid workspace keeps working until the end of its paid period, then enters the 30 days. - After 30 days it is **permanently deleted** (mailboxes, synced mail, campaigns, contacts you added, settings) and cannot be recovered. Purchased credits and quota blocks end with it. - You get reminder emails during the 30 days. ## Things deleted immediately - **Mailbox passwords and tokens** are deleted the moment you disconnect a mailbox in **Accounts**. - **Synced inbox mail** for that mailbox is deleted with the mailbox when you disconnect it. The Privacy Policy commits to at most 30 days. ## Hosted (OneMail) mailboxes If a hosted mailbox is cancelled or stops being paid for, the mailbox and its mail are kept for a recovery window and then deleted. When a paid workspace ends, mailboxes billed on it may be suspended and later deleted the same way. See [OneMail](https://docs.warmerly.com/help/onemail-mailboxes). ## Things kept for longer, on purpose - **Tax and accounting records** are kept for as long as the law requires (currently 6 years under UK law). Payment records are held by Stripe as well. - **Opt-out records.** Addresses that hard-bounced, or whose owner asked to be erased, are kept on a platform-wide suppression list indefinitely. Deleting the record of an opt-out would risk contacting that person again. Your workspace's own do-not-contact list is kept while the workspace exists. See [Suppression](https://docs.warmerly.com/suppression). - **Security and audit logs, and records of privacy requests,** are kept as long as needed to protect the service and show legal obligations were met. - **Support conversations** are kept while they may be needed to help you, and while your account exists. ## Shorter windows on other records Some records are deleted on a schedule regardless of your plan. For example, warmup activity logs after 12 months, and in-app activity records after 90 days. The complete list and current periods are in section 8 of the [Privacy Policy](https://warmerly.com/privacy). ## How do I delete my personal data or my account? Deleting a workspace removes the workspace's data. To have your **personal data** erased, or to ask what is held about you, send a [privacy request](https://docs.warmerly.com/help/privacy-requests). We act on requests within one month. The app has no separate "delete my account" button beyond deleting your workspaces. ## Can I export my data first? Leads can be exported from the tool that holds them, subject to your plan's lead export allowance. For a copy of your personal data, use a [privacy request](https://docs.warmerly.com/help/privacy-requests) and choose **Access a copy of my data**. Do this before the 30 days on a deleted workspace run out. ## Common problems **"I cancelled and my campaigns stopped."** Most likely you are over Free's limits, so sending is paused. Nothing is deleted. Reduce usage or choose a plan. **"I deleted a workspace by mistake."** Restore it within 30 days from **Settings > Workspaces**. **"I want everything gone now."** Send a privacy request and ask for deletion. Some records must be kept (above), and the request is acted on within one month. ## Related - [What is Warmerly's refund and cancellation policy?](https://docs.warmerly.com/help/refunds-and-cancellation-policy) - [Privacy requests](https://docs.warmerly.com/help/privacy-requests) --- # My account is suspended. What can I do and how do I appeal? If your account is suspended, you can still sign in, but you are taken to a **suspended** screen that shows the reason and lets you send an **appeal**. Your data is safe and nothing is deleted. While it is suspended, your workspaces' sending and warmup are paused. Only a person on the Warmerly team can lift a suspension, and every appeal is read by a person. ## What you see Signing in with your correct email and password takes you to the **Account suspended** screen instead of the dashboard. If you use Google or Microsoft sign-in, the same happens. On the Android app you get a message that the account is suspended, because the app cannot show the page, and you can use the website to appeal. The screen shows: - The reason, with a short explanation. - Whether an appeal is under review, or when your last appeal was declined. - A form headed **Appeal this suspension**, and a **Sign out** button. - Warmi, the support assistant, docked on the page. Warmi can explain your situation and file an appeal for you, but it cannot lift a suspension and it cannot promise that an appeal will succeed. ## What stops while suspended - Campaign sending, email warmup, LinkedIn warmup and WhatsApp sending for the account's workspaces are paused, including for teammates who use a workspace owned by a suspended account. Campaigns stay as they are and nothing is deleted. - The dashboard is unavailable; you are sent to the suspended screen. - Programmatic access is refused: the API returns an `account_suspended` error, for both sessions and API keys. Connected AI apps stop working too. When the suspension is lifted, everything picks up again on its own. Nothing has to be set up again. ## The reasons The screen shows one of these: - **Multiple accounts:** our automatic security checks found that more than one account looks like it was set up by the same person. Each person can have one account, and free plans are for one account only. - **Usage policy:** activity on the account did not follow the usage policy. See the [Acceptable Use Policy](https://warmerly.com/acceptable-use). - **Payment review:** a problem with the account's payment details is being reviewed. - **Account under review:** the team is reviewing the account. For a suspension about multiple accounts, the screen goes further: see below. For every other reason it does not say how something was noticed, and support cannot share that either. ## Automatic account security: a second account When a new account is created, Warmerly's automatic security checks look for a second account set up by someone who already has one. If they find one, the **new** account is paused and the **first** account is never touched. Nothing is deleted. The paused account's screen shows: - **This account** (marked Paused) and **Your first account** (marked Active), side by side. Your own details are shown in full. The other account is partly hidden (for example `k***@gmail.com` and `203.0.x.x`), because a match can be wrong and we never show one person another person's address. - What the two had in common, for example the same name or the same city. - Four ways forward: - **Use my first account.** Sign out and sign in with your first account. - **Keep both.** Start a paid plan and this account is unlocked as soon as your plan is live. Free plans are for one account per person, so paying is what lets you keep a second. - **Close this account.** Removes it and its workspace. You have 30 days to ask us to restore it. - **This is not me.** Two people can share a network or a name. Send an appeal and a person will look. You also get an email when this happens, so you do not have to find out by signing in. ## How do I appeal? 1. Sign in. You land on the suspended screen. 2. In **Appeal this suspension**, write what happened and why you think it is a mistake. The box takes between 20 and 2,000 characters. 3. Click **Send appeal**. The screen changes to "Your appeal is under review". Or tell Warmi your side. It will show you the exact wording, ask you to confirm, then file it. Limits and rules: - One appeal can be open at a time. - You can file up to 3 appeals in 24 hours. - Be specific and honest. Say which mailbox, campaign or payment you think was affected and what actually happened. A typical response time is not a promise. ## What happens next - **Approved:** you get an email, access is restored and your next page load takes you to the dashboard. Sending and warmup resume. - **Declined:** you get an email saying a decision was made. The screen shows "Your last appeal was declined on (date)". You can send another appeal if you have new information, or reply to the email. ## Common problems **"I cannot sign in with Google or Microsoft."** If the sign-in is refused with an `account_suspended` message rather than opening the suspended screen, use email and password sign-in on the website to reach the appeal form. **"My teammate's campaigns stopped."** They use a workspace owned by a suspended account. The owner's suspension pauses that workspace's sending. **"I need something from the account while suspended."** Access is paused until the review is done. You can still email support@warmerly.com, but an appeal is the way to have it reviewed. **"I think this is a billing problem, not a policy one."** See [Why is my workspace locked?](https://docs.warmerly.com/help/billing-locked). A billing lock is different from a suspension: it clears by fixing payment or usage. ## Related - [Sign in and account security](https://docs.warmerly.com/help/sign-in-and-security) - [Warmerly Terms of Service](https://warmerly.com/terms) --- # How do I access, correct or delete my personal data? Use the form at [warmerly.com/privacy-request](https://warmerly.com/privacy-request), or email privacy@warmerly.com (it goes to the same place). **You do not need an account and you do not need to give a reason.** Warmerly acts on a request within one month, usually much sooner. This is for anyone: customers, and people who are not customers but whose business contact details appear in Warmerly's lead database. ## What can I ask for? The form's **What would you like us to do?** menu has six options: | Option | What it means | | --- | --- | | Know what data you hold about me | We tell you what personal data we have about you. | | Access a copy of my data | You get a copy of it. | | Correct inaccurate data | We fix data that is wrong. | | Delete my data | We delete it, subject to the exceptions below. | | Object to processing | You object to how your data is being used. | | Opt out of sale/sharing (CCPA/CPRA) | For California residents. See the [US privacy notice](https://warmerly.com/us-privacy). Warmerly does not sell customers' personal data. | ## How do I send a request? 1. Open [warmerly.com/privacy-request](https://warmerly.com/privacy-request). 2. Choose what you would like done. 3. Enter **Your email or how we can identify your data**: normally your email address, or your name and company if that is what we would have on file. 4. Optionally add details that help us find your data faster, such as a domain, a company name or where you think we got it. 5. Click **Submit request**. The page says "Request received". If the form fails, it tells you to email privacy@warmerly.com directly. ## What happens next? - We may first ask you to confirm that the address or domain is yours, so nobody can see or remove someone else's details. - We act within one month. - Some records must be kept even after a deletion request, for legal reasons. See below. ## Customer or not, which page applies? - **You are a Warmerly customer:** the [Privacy Policy](https://warmerly.com/privacy) explains what we hold about you and your workspaces, and how long. See also [What happens to my data if I cancel or delete?](https://docs.warmerly.com/help/data-after-cancelling-or-deleting). - **You are not a customer, but your business email appears in a lead database or came from someone's campaign:** the [Prospect Privacy Notice](https://warmerly.com/prospect-privacy) explains where the data comes from and how to object. To stop a particular sender's emails, use the unsubscribe link in that email as well. - **You just want your workspace gone:** delete it in Settings > Workspaces. See [Delete or restore a workspace](https://docs.warmerly.com/help/delete-or-restore-workspace). That is not the same as a privacy request for your personal data. ## What can not be deleted? A deletion request cannot remove everything. Warmerly keeps: - Tax and accounting records, for as long as the law requires. - Records that someone opted out or asked to be erased, so they are not contacted again. - Security and audit logs and records of privacy requests, for as long as needed to protect the service and show obligations were met. The full list is in section 8 of the [Privacy Policy](https://warmerly.com/privacy). ## Does this cancel my subscription? No. A privacy request is separate from billing. To cancel a paid plan, use **Manage billing** in **Settings > Billing**. See [How do I cancel or change my plan?](https://docs.warmerly.com/help/cancel-or-change-plan). ## Common problems **"I never heard back."** Give it time; the deadline is one month. If it has passed, email privacy@warmerly.com and quote the address you used on the form. **"I want to stop getting Warmerly's own emails."** Use [Email preferences](https://docs.warmerly.com/help/email-preferences). Sign-in, billing and invitation mail always sends. ## Related - [Sign in and account security](https://docs.warmerly.com/help/sign-in-and-security) - [Privacy Policy](https://warmerly.com/privacy) --- # How do I use the Warmerly Android app? Warmerly for Android is built for the part of outreach that cannot wait: knowing the moment a prospect replies, and answering. It also shows your mailbox health and warmup, lets you pause or resume a campaign, and has a chat with Warmi, the support assistant. It is Android only. There is no iPhone version. It is a companion to the web app, not a copy of it. Building campaigns, importing lead lists and the detailed analytics stay on the web. ## Install it 1. On your phone, open [warmerly.com/android](https://warmerly.com/android) and tap **Download for Android**. You need to be signed in to Warmerly to download it. 2. Warmerly is not on the Play Store, so Android asks you once to allow installs from that source. Allow it for the browser or file manager you used, then open the file to install. 3. Open the app and sign in (below). After that the app checks for new versions when it opens, and you can check by hand under **Settings > About > Check for updates**. It downloads the update and hands it to Android's installer, which asks you to confirm. ## Sign in or create an account You can use an existing account or create one on the phone. - **Sign in** with your email and password, or **Continue with Google**. - **New account:** the app walks you through setup: what you want to use Warmerly for, then **Google**, **Microsoft** or **email** signup. If you sign up with email, you must confirm your address from the email we send before you can go on. The app waits on a "check your inbox" screen and lets you resend the email. - **Connect a mailbox** during setup: **Gmail** (with a Google app password), **Microsoft 365 / Outlook** (one tap, you sign in with Microsoft), **Zoho Mail**, or **Other (IMAP / SMTP)**. The app then shows your SPF, DKIM and DMARC checks and lets you pick a warmup ramp (the setup offers Safe, Balanced or Faster, with Balanced preselected). Nothing after connecting the mailbox blocks you: if a DNS check fails you can carry on and fix it later from a computer. - The phone uses the same session as the web. If you are signed out on the web (for example you revoke the session), the phone signs out too and asks you to sign in again. If you are on the Free plan you stay on it. The app does not sell plans: paid plans are managed on the website, at [warmerly.com/pricing](https://warmerly.com/pricing). ## What you can do in the app The bottom bar has **Home**, **Accounts**, **Inbox**, **Campaigns** and **Settings**. - **Inbox:** replies from every mailbox in one list, with an unread badge on the tab. Open a thread to read the conversation and type a reply. - **Home:** your health score, active, warming and paused mailboxes, today's sends, and the mailboxes that need attention. - **Accounts:** open a mailbox to see its overview and placement results, turn its warmup on or off, and resume a paused mailbox. - **Campaigns:** sent, replies and reply rate for each campaign, with **Pause** and **Resume**. - **Leads:** the **Leads** button on the **Campaigns** tab. Browse leads, open one, and add a lead to a campaign you choose. Bulk CSV import stays on the web. - **Chat with Warmi:** from Settings. The same assistant as the dashboard. When you are signed in it can look up your own account, for example why a mailbox stopped sending. See [Warmi, the support assistant](https://docs.warmerly.com/help/warmi-support-assistant). - **Workspaces and projects:** if you have more than one, switch from Settings and the whole app follows. ## Push notifications The app sends a push notification when a genuine reply arrives. - **Only genuine replies.** Warmup traffic between mailboxes on Warmerly never notifies you, and neither do automated senders such as bounces and no-reply addresses. That is what keeps the notification worth reading. - **Not instant.** Replies are read from your mailboxes about every 5 minutes, so a notification can arrive up to about 5 minutes after the reply lands. - **Tap** the notification to open that thread directly. - **Reply from the lock screen.** The notification has a **Reply** action. Type your answer and tap **Send** without opening the app. If it cannot be sent you get a "Reply not sent" notification instead. The app never queues a reply to send later, so you always know whether it went. - **Turn it off** under **Settings > Notifications > Push for new replies**. This only affects phone notifications. It does not change any email you get from Warmerly. - **Signing out** on the phone stops notifications to that phone. ## What the app does not do - No campaign builder or sequence editor. Use the web app. - No lead CSV import, no analytics dashboards, no billing or plan changes. - No offline sending. If you are offline you can read what was cached, but a reply will not be sent until you are connected. - No iPhone or iPad app. ## Common problems **I am not getting notifications.** Check that Android allows notifications for Warmerly, that **Push for new replies** is on in **Settings**, and that the sender is a real person: bounces, no-reply addresses and warmup mail never notify. A reply can also take up to about 5 minutes to arrive. If you are signed in on the phone but nothing ever arrives, ask Warmi in the app. **The install is blocked.** Android needs your permission to install from the source you downloaded it with. Allow it in the prompt or in Android's install-unknown-apps settings, then open the file again. **I was signed out.** Sessions are shared with the web. If the session was revoked or expired, sign in again. Your data is on your account, not on the phone. **I cannot connect my mailbox on the phone.** Gmail needs a Google app password and Google Workspace admins must allow it. Do it on a computer with [Connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection) if that is easier. ## Related - [Getting started checklist](https://docs.warmerly.com/help/getting-started-checklist) - [Reconnect a mailbox](https://docs.warmerly.com/help/reconnect-mailbox) - [How warmup works](https://docs.warmerly.com/how-warmup-works) --- # What can Warmi, the support assistant, do (and how do I reach a human)? Warmi is Warmerly's AI support assistant. Ask it a question in plain words and it searches these docs, reads the right page and answers from it. When you are signed in it can also look at your own account to explain what it sees. If it cannot solve your problem, or you just want a person, it hands the conversation to the Warmerly team. Warmi is an AI. It is not a person, and it can be wrong, so for anything involving money or a decision you cannot undo, check what it tells you against the page it links. ## Where to find it - **In the app:** the **Ask Warmi** button at the bottom right of every dashboard page. - **On warmerly.com and docs.warmerly.com:** the same button at the bottom right, no account needed. - **In the Android app:** **Settings > Chat with Warmi**. See [the Android app](https://docs.warmerly.com/help/android-app). - **By email:** write to support@warmerly.com. Warmi answers there too, and replies come from a Warmerly mail address. - **On some screens**, such as campaign pages and the billing screen shown when a workspace is locked, Warmi also appears inside the page itself. The chat keeps your past conversations. Open the conversation list to continue an old chat or choose **Start a new chat**. If a person on the team replied to you, their name shows in the list and the launcher tells you when there is an unread reply. ## What Warmi can do for anyone - Answer how-to and troubleshooting questions from these docs, and tell you where in the app to click. It uses the exact page names from the sidebar and Settings. - Run a **DNS check on a domain you name** (SPF, DKIM, DMARC and MX) and explain what to fix, with a link to the full report. It will not check free mail providers such as gmail.com, because you cannot edit their DNS. - Tell you the current plans and prices, and quote a domain price. It never buys a domain. - Read public pages on warmerly.com. - Check the [service status](https://docs.warmerly.com/help/status-page) first when you report something failing, and tell you plainly if there is a current incident. - Answer in your language when you write in one. Page and menu names stay in English, as they appear in the app. ## What Warmi can do when you are signed in With your account, Warmi can read (never change) things like: - your mailboxes: warmup state, health, and stored DNS results; - campaign statistics; - a summary of replies that look like leads in your inbox; - your LinkedIn and WhatsApp accounts; - your transactional email domains and delivery numbers; - your plan, usage against your limits, and why a workspace is locked, if it is. This is why asking "why did my mailbox stop sending?" works better signed in: Warmi can look instead of asking you to describe a screen. It can also **run a placement test** on one of your mailboxes. That sends real probe emails and uses one of your monthly placement tests, so Warmi always tells you which mailbox it would test and how many tests you have left, and asks before it runs one. Every lookup or action Warmi takes is shown in the chat as it happens, with what it found. If you email support, Warmi may recognise your address as an account. That is not a sign-in, so in email it can only see your plan and whether a workspace is billing-locked. It cannot see mailboxes, campaigns, leads or inbox. ## What Warmi cannot do - **It cannot change your plan or take a payment.** No upgrade, downgrade, cancellation, trial, discount, refund or card change. It has no such ability, so it cannot be talked into it. You do those yourself under **Settings > Billing** (see [Cancel or change plan](https://docs.warmerly.com/help/cancel-or-change-plan)). Exceptions and disputes go to the team. - **It cannot change your account data.** It cannot edit campaigns, connect or remove mailboxes, or change roles. It tells you where to do it. - **It cannot unlock a locked workspace.** It can say why it is locked and what clears it. - **It cannot reach developers or product.** Feedback and feature requests only reach a person if Warmi hands the conversation to the team. - **It will not say which AI model runs it.** It is Warmi. - **It does not promise deadlines,** outcomes or fixes it cannot decide. ## How do I reach a human? Just say so: "I want to talk to a person." Warmi hands the conversation to the Warmerly team. You do not have to sign up, log in or fill in a form first. - **Signed in:** the team already has your account email, and follows up by email. - **Not signed in:** Warmi asks once for an email address. Without one, the team can read the conversation but cannot email you, so check back in the chat. - **What happens next:** a person reads the whole conversation. Replies come to your email, and also show in the chat with the person's name. These docs do not state a guaranteed response time, and Warmi is told not to invent one. - **Already sent?** If the conversation is already with the team, Warmi says so and adds your new message to the same ticket instead of opening a second one. - **By email:** write to support@warmerly.com, with screenshots or PDFs if it helps (up to five files per email, each up to 10 MB, in PNG, JPEG, WebP, GIF or PDF format). Reply to a team member's email to keep the same thread. Warmi does not answer a message addressed to a person. You can also book a free 15-minute setup call with the founder: **Settings > Book a 1:1 setup call**, or [warmerly.com/book-a-call](https://warmerly.com/book-a-call). ## Tips for better answers - Say what you were doing and what you saw: the exact message on screen is worth more than a summary. - Name the mailbox or campaign, or sign in so Warmi can look for itself. - If the answer feels wrong, say so and ask it to check the docs again, or ask for a person. ## Common problems **Warmi says it hit a snag or gives no answer.** The assistant depends on an AI provider. Try again in a moment, or email support@warmerly.com. A domain check can still work when the model is unavailable. **Warmi told me it passed something to the team but I heard nothing.** Warmi only says that after it actually opens a ticket. If you gave no email address, nobody can email you: look in the chat for a reply, or write to support@warmerly.com. **I asked Warmi to upgrade me.** It cannot. Use **Settings > Billing**. ## Related - [Frequently asked questions](https://docs.warmerly.com/faq) - [Troubleshooting](https://docs.warmerly.com/troubleshooting) - [Is Warmerly down? The status page](https://docs.warmerly.com/help/status-page) - [Use Warmerly with AI (MCP)](https://docs.warmerly.com/ai) to use your own assistant with your account instead --- # How do I connect, check or revoke an AI app (Claude, ChatGPT, Cursor)? You can let an AI assistant such as Claude, ChatGPT, Claude Code or Cursor work inside one of your Warmerly workspaces. You approve it once on a Warmerly screen, and you can cut it off at any time under **Settings > Connected apps**. This page covers that approval screen and the management page. The server address, per-client setup steps, the tool list and the guardrails are on [Use Warmerly with AI (MCP)](https://docs.warmerly.com/ai). It is available on every plan, including Free. No API key is needed. ## Connect an assistant 1. In **Settings > Connected apps**, copy the server address shown at the top, or use the setup steps for your assistant right below it. The same panel has a copyable setup prompt for coding agents and install buttons for Cursor and VS Code. The dashboard also shows a "Run Warmerly from ChatGPT, Claude or Cursor" card until you connect your first app or dismiss it. 2. Add Warmerly as a connector or MCP server in the assistant, following [the steps for your client](https://docs.warmerly.com/ai). 3. The assistant opens a Warmerly page titled "Sign in with Warmerly". Sign in if asked. That is the approval screen, described next. ## What the approval screen shows The page says which app "wants to use your Warmerly account" and where it will send you back to (the web address after "Redirects to"). It lists what approving lets the app do in the workspace you choose: - read your mailboxes, campaigns, leads, inbox and transactional email; - create, launch, pause and resume campaigns, and add leads to them; - reply to your inbox and send transactional email on your behalf; - verify and find email addresses, and manage your suppression list. Every action stays inside your plan's limits and is logged with the app's name. **Choose the workspace.** If you have more than one workspace, a **Workspace** menu lets you pick. The connection is tied to that one workspace. It cannot see or change your others. To use another workspace from the same assistant, connect again and pick it. Then click **Allow**, or **Cancel** to refuse. Nothing is granted until you click **Allow**. ### If the screen says "unverified app" Apps name themselves, so a name on this screen proves nothing. When Warmerly does not recognise the address the app will send you back to, the heading says "(unverified app)" and a warning names that address. Only click **Allow** if you started connecting that app yourself, just now, from that site. If someone sent you a link and asked you to approve it, click **Cancel**. Apps that run on your own computer (Claude Code and Cursor, for example) show a note that they connect an app running on this computer. ### If the screen shows an error instead A page with an error title (for example "Unknown client" or "Invalid redirect") means the app's request was incomplete or not valid, so Warmerly refuses to send you anywhere. Start the connection again from the assistant. If it keeps happening, the app is at fault, not your account. ## See what is connected Open **Settings > Connected apps**. Each row shows: - the app's name and the web address it belongs to, - the workspace it can use, - when it was connected and when it was last used ("never" if it signed in but has not made a request). An app you approved but never finished connecting does not appear. The list shows only apps that signed in. ## Revoke access 1. Open **Settings > Connected apps**. 2. Click **Revoke** on the app's row. 3. Confirm **Revoke access** in the dialog. The app loses access to that workspace immediately. Revoking removes every connection that app holds for that workspace, not just the newest one. To let it back in, connect it again from the assistant and approve the screen again. Access also ends by itself when you are removed from the workspace or the workspace is deleted. It does not come back if you are re-invited or the workspace is restored. Connect the app again. ## What an assistant can and cannot do Everything an assistant does goes through the same checks as the dashboard: your plan limits, the suppression list, mailbox health and the billing lock. It never sees a mailbox password, and connecting a mailbox always happens in Warmerly itself. It can only touch the workspace you chose. Actions that send or change something are written to your **Audit log** (under **Settings**) with the app's name, so you can see what it did. Merely reading data is not logged. The full list of guardrails is on [Use Warmerly with AI (MCP)](https://docs.warmerly.com/ai#guardrails). ## Common problems **The assistant says it lost access or got a 401.** The connection was revoked or expired. Reconnect it. If an app has not been used for a long time it may ask you to sign in again. **The assistant sees the wrong workspace.** Each connection is pinned to one workspace. Connect again and pick the other one. **I do not see the Workspace menu.** It only appears when you have more than one active workspace. **There is nothing in Settings > Connected apps.** Either no app has finished signing in yet, or you are looking at a different account than the one you approved with. ## Related - [Use Warmerly with AI (MCP)](https://docs.warmerly.com/ai) - [Platform API keys and authentication](https://docs.warmerly.com/authentication) (a different thing: keys for code you write yourself, Agency plan) - [Warmi, the support assistant](https://docs.warmerly.com/help/warmi-support-assistant) --- # Is Warmerly down? How the status page and incident banners work Check [status.warmerly.com](https://status.warmerly.com). It is a public page, no sign-in needed, that shows whether each part of Warmerly is working right now, its uptime over the last 90 days, and any incident we are working on. Warmi reads the same information, so asking it "is Warmerly down?" gets you the same answer. Before you assume a fault on our side, it is worth a look: a mailbox that is not sending, a campaign that stalled or a page that will not load is often explained by an incident that is already posted. ## What the page shows At the top is one headline: | Headline | Meaning | | --- | --- | | **All systems operational** | Every monitored component is working. | | **Some systems are degraded** | Something is slower or partly failing. | | **Some systems are down** | At least one component is not working. | | **Status checks are delayed** | The checks themselves have not reported for a few minutes, so the page will not claim anything is fine. Treat it as "not confirmed", not as "all clear". | Below it, each component has its own status, grouped like this: - **Core:** Website, Dashboard, API, Database, and Global reachability (an independent check from outside our network that the website and dashboard answer on the public internet). - **Email infrastructure:** Hosted mailboxes (OneMail), Free trial mailboxes (the server behind the free mailbox every account gets), Mail delivery, Mail server reputation, Mail server encryption, and Account emails (sign-in links, password resets, notifications). - **Sending engines:** Warmup, Campaign sending, Email verification. - **Integrations:** Inbox sync, WhatsApp and LinkedIn. - **AI:** AI features (Warmi, AI openers and AI-written replies). Open a component's **Last 24 hours and uptime** section to see uptime over 24 hours, 7, 30 and 90 days, an hourly strip for the last day, and, where it applies, response time. Each day in the 90-day bar is coloured by how many of that day's checks failed. A single restart does not paint a whole day red. A component that is deliberately switched off, not broken, shows as **Under maintenance** with a short note. It is left out of uptime and out of the headline. Planned work can also appear as a maintenance incident. ## Incidents When something needs explaining, we post an **incident** with a title, which components it affects, and a series of timestamped updates. An incident moves through **investigating, identified, monitoring** and **resolved**. **Active incidents** are listed at the top, and **Past incidents** below, each with a link of its own you can share. Some incidents are opened **automatically** by our monitoring when a component has been down without a break for a few minutes. These say so in their first update, and they close themselves when the component recovers, unless a person has posted an update, in which case a person closes it. A single bad check never opens an incident. ## In the app You do not need to remember to check. While you are in the dashboard, a banner appears above the page when a component is confirmed degraded or down, or when there is an active incident. It names up to two components (for example "Free trial mailboxes: not working right now"), and links to the status page. It hides itself when things recover. If you dismiss it, it stays hidden until something new or worse happens. Pages that do not exist (a 404) also show a small status line: "Check service status", or "All systems operational" when checks are reading normally. ## Follow incidents - **RSS:** subscribe to [status.warmerly.com/feed.xml](https://status.warmerly.com/feed.xml) in any feed reader. - **Email subscriptions:** there are none. The feed is the way to follow along. - **Ask Warmi:** it checks the status first when you report something failing. ## What the status page does not tell you It shows the health of Warmerly's own services. It does not show a problem with your own mailbox, domain or account. If everything reads operational and something is still wrong for you, that is a problem on your side of the setup: a paused or disconnected mailbox, a DNS record, a plan limit or a billing lock. See [Troubleshooting](https://docs.warmerly.com/troubleshooting), or ask Warmi to look at your account (see [Warmi, the support assistant](https://docs.warmerly.com/help/warmi-support-assistant)). ## Common problems **The page says operational but my mailbox is not sending.** Open the mailbox on **Accounts** and check its status, then [Reconnect a mailbox](https://docs.warmerly.com/help/reconnect-mailbox) if it says it needs reconnecting. A campaign that is not sending has its own checklist under [A campaign is not sending](https://docs.warmerly.com/troubleshooting#a-campaign-is-not-sending). **A banner shows in the app but the status page looks fine.** The banner needs a couple of consecutive failed checks to appear, and it clears when the component recovers. Refresh the page. **"Status checks are delayed."** The monitoring itself is behind. Check again in a few minutes. If it persists, email support@warmerly.com. ## Related - [Troubleshooting](https://docs.warmerly.com/troubleshooting) - [Frequently asked questions](https://docs.warmerly.com/faq) - [Warmi, the support assistant](https://docs.warmerly.com/help/warmi-support-assistant) --- # Where do I see what's new in Warmerly? There are three places, depending on what you want to know: | You want | Go to | | --- | --- | | New features and fixes, in the app | The **megaphone icon** at the top right of dashboard pages, which opens **What's new in Warmerly** | | Every product update, newest first, for anyone to read | [warmerly.com/changelog](https://warmerly.com/changelog) | | Changes to the public API and these docs | [API Changelog](https://docs.warmerly.com/changelog) | ## The What's new list in the app Open any dashboard page and look for the megaphone icon in the page header (its label is **Product updates**). Click it and a window titled **What's new in Warmerly** opens with a plain list: the date, the title and a one-line summary of each update. - If there are updates you have not seen, the window says how many are new "since your last visit" and lists those. - If there are none, it shows **Recent updates**, so you can still look back at the latest few. - **View all updates** opens the full public changelog. - **Got it** closes the window. - If there are more new updates than the window lists, a line at the bottom says how many more are in the full changelog. ### The number on the megaphone A badge on the icon counts updates published since you last opened the list. Closing the list marks the latest update as seen and clears the badge. The badge counts only updates published **after your account was created**. A new account starts at zero instead of showing every update the product has ever had. ### When it opens by itself The list can open on its own when you return to the dashboard, but only when all of these are true: - your account is at least 7 days old, - there are updates you have not seen, - you did not just arrive from signup, and - no other window is open. It waits a few seconds, and it waits behind any other dialog (for example a plan-limit prompt) rather than covering it. It opens at most once per browser session for the newest update, with a short burst of confetti. The confetti is skipped if your device is set to reduce motion, or if you have turned on **Calm Warmi down** under **Settings > Profile**. Press **Escape** to close it at any time. You are never forced to look at it: closing it once is enough for that update. ## The public changelog [warmerly.com/changelog](https://warmerly.com/changelog) lists every product update, feature and fix, newest first. You do not need an account to read it. It is where **View all updates** goes. ## The API changelog If you use the [Warmerly API](https://docs.warmerly.com), the [API Changelog](https://docs.warmerly.com/changelog) tracks changes to the endpoints and these docs, including fixes and anything being deprecated. Product feature announcements are not repeated there. They are in the two places above. ## Common problems **I never see the list open by itself.** That is expected in your first week, and when you have no unseen updates. The megaphone always works. **The badge is gone but I did not read the updates.** Closing the list clears the badge. Open it again from the megaphone to see **Recent updates**, or read the public changelog. **A feature the changelog mentions is not in my account.** Some features depend on your plan. Check [Plans & limits](https://docs.warmerly.com/plans-and-limits), or ask Warmi. ## Related - [Dashboard overview](https://docs.warmerly.com/help/dashboard-overview) - [Is Warmerly down? The status page](https://docs.warmerly.com/help/status-page) --- # How do I start sending app emails with Warmerly transactional email? Transactional email is for the mail your own app sends to its users: password resets, receipts, sign-in links and notifications. Open the product switcher at the top of the sidebar and choose **Transactional email**. It has its own sidebar (**Overview**, **Emails**, **Metrics**, **Domains**, **Sending keys**, **Plan & billing**), its own keys and its own billing. It is a separate product from cold outreach. It sends on separate infrastructure, so the reputation of your campaigns can never put your password resets in spam. For the same reason, send app mail from a domain or subdomain (such as `mail.yourcompany.com`) that you do **not** use for cold outreach. This page is the click-by-click start. The request and response details for developers are in the [Transactional email API reference](https://docs.warmerly.com/transactional). ## Set up in five steps The **Overview** page shows a "Get set up" checklist that ticks itself off as you go. When all four of its steps are done it collapses to "Setup complete". 1. **Add a sending domain.** Open **Domains**, type the domain or subdomain you will send from (for example `mail.yourcompany.com`) and click **Add domain**. Use one that already receives email, or a subdomain of one: Gmail and Outlook distrust mail from a domain nobody can reply to. 2. **Publish the DNS records.** Click **Show DNS records**. Copy each record to your DNS provider (the guides for [DKIM](https://docs.warmerly.com/guides/dkim) and [DNS records](https://docs.warmerly.com/guides/dns-records) show where). You add three DKIM records, plus a bounce record pair and a DMARC record. There is no record on your root domain: your own SPF and MX are untouched, so your regular email keeps working exactly as it does today. 3. **Verify it.** Press **Verify**. DNS changes can take a few minutes to show up, so if some records show **Missing**, wait and press **Verify** again. Once verified you can send from the domain, and the button reads **Re-check** from then on. 4. **Create a sending key.** Open **Sending keys**, click **Create key**, name it (for example "Production") and choose a permission: - **Sending only:** can send email. It cannot read your emails or change domains. Use this in your application. It can be limited to one domain. - **Full access:** can send, read emails and add or verify domains. Copy the key when it is shown. It is displayed once and cannot be shown again, so store it somewhere safe. Only workspace owners and admins can create keys. 5. **Send your first email.** On **Overview**, use **Send a test email**: pick the from address and domain, type your own address in **To**, and click **Send test**. The email appears under **Recent emails**. The same page has **Send from your code** with ready-made snippets. ## Send from your code Send the key as a bearer token in the request header, and add an `Idempotency-Key` header so a retried request never sends twice. The endpoint, fields and error codes are in the [API reference](https://docs.warmerly.com/transactional). A transactional key (it starts with `wm_tx_`) works only on transactional endpoints. It is not the same as the [Platform API keys](https://docs.warmerly.com/keys) under **Settings**, and neither works in place of the other. ## Read your results - **Emails:** every email you sent, with a status. Search by recipient or subject, and filter by status, sending domain and date range. Click an email to see its **Timeline** of delivery events. The message body is kept for 30 days, and the rest of the record stays. - **Metrics:** volume, delivered rate, bounce rate and complaint rate over 7, 30 or 90 days, for all domains or one. - **Overview:** recent emails, a sending-health panel, and a warning if a verified domain starts failing its checks. - **Domains:** each domain shows a health checklist with a score, so you can see what to fix. The statuses are `queued` (waiting to be sent, retried for up to 24 hours), `sent`, `delivered`, `deferred`, `bounced`, `complained`, `failed` and `suppressed`. Their meanings are in the [API reference](https://docs.warmerly.com/transactional#statuses). ## Bounces, complaints and your suppression list An address that hard-bounces or marks an email as spam is added to your **Do not contact** list automatically, and nothing is sent to it again. An email whose recipients are all suppressed is recorded as `suppressed` and is not sent. Watch your **Bounce rate** and **Complaint rate** on **Metrics**. The dashboard states that a sender is reviewed at 5% bounces or 0.1% complaints and can be paused. If sending is paused, the Overview shows "Sending is paused for this workspace" and new sends are refused until it is reviewed. Stop sending to addresses that bounce, check where the list came from, then contact support. ## Plan and billing Transactional email is billed **separately** from your outreach plan, and one email is one recipient. Under **Plan & billing** you can see your current plan and this month's use, switch plan, choose monthly or yearly billing, and turn pay-as-you-go overage on or off. Only the workspace owner can change the plan. Overage is opt-in: nothing past your allowance is charged unless you switch it on. Prices, allowances and the free tier are on the [transactional email pricing page](https://warmerly.com/transactional-email#pricing) and in the app, not repeated here. An outreach plan does not include transactional sending, and the reverse is also true. ## What is not possible - You cannot send from a domain you have not verified. - A sending key cannot be used for campaigns, leads, the inbox or any other Warmerly API. - Transactional email is not for cold outreach. Use [Campaigns](https://docs.warmerly.com/help/launch-first-campaign) for that. ## Common problems **A DNS record shows Missing.** Copy the host and value exactly. Some DNS providers add your domain to the end of the host automatically, so paste only the part before your domain. Wait a few minutes and press **Verify** again. **The API answers 403 sending_paused.** Sending is paused for the workspace because of its bounce or complaint rate. See the section above and contact support. **The API answers 429.** You are past the request rate limit or your plan's allowance. Check **Plan & billing**, or see [Errors & rate limits](https://docs.warmerly.com/errors). **I cannot add a domain.** The domain may already be in use elsewhere in Warmerly (for example as a OneMail domain or in another workspace), or you have reached your plan's domain limit. **The email is delivered but lands in spam.** A new domain has no reputation yet. Send mail your users asked for first and grow volume over a few weeks, send HTML together with a plain-text part, and read your DMARC reports. See the "Deliverability" section of the [API reference](https://docs.warmerly.com/transactional#deliverability). ## Related - [Transactional email API reference](https://docs.warmerly.com/transactional) - [Authentication](https://docs.warmerly.com/authentication) and [API keys](https://docs.warmerly.com/keys) - [Suppression list API](https://docs.warmerly.com/suppression) - [Glossary of Warmerly terms](https://docs.warmerly.com/help/glossary) --- # What am I looking at on my Warmerly dashboard? The **Dashboard** (the first item in the sidebar) is your overview. It answers three questions at a glance: are my mailboxes healthy, is warmup running, and what needs my attention. This page walks through it from the top down. The Dashboard shows the workspace you have selected. ## Add mailbox The **Add mailbox** button at the top right opens the mailbox wizard on **Accounts**. See [Connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection) or [OneMail](https://docs.warmerly.com/help/onemail-mailboxes) if you would rather have Warmerly host it. ## The "Get started with Warmerly" card New workspaces see a checklist card at the top. It usually has up to two steps: 1. **Connect a mailbox**, with a second link, **Get a domain + mailbox**, if you have none yet. 2. **Create your first campaign**, shown if you told the setup wizard you want to do outreach. The card hides itself once every step that applies is done. There is nothing to dismiss. The free mailbox every account gets (see [free sending mailbox](https://docs.warmerly.com/help/free-sending-mailbox)) is shown above the steps while you have not connected a mailbox of your own. It does not count as the "connect a mailbox" step, because it was set up for you. If you have not connected an AI assistant yet, a card "Run Warmerly from ChatGPT, Claude or Cursor" may also appear. Click **Set it up**, or the cross to dismiss it. See [Connected apps](https://docs.warmerly.com/help/manage-connected-ai-apps). ## Warmup status line and alerts - **Warmup is running** (with a green dot) means Warmerly's background system is actively sending and checking your warmup emails right now. If it says warmup is paused or has not run recently, check the [status page](https://docs.warmerly.com/help/status-page) first. - **Alert banners** appear for recent warnings and critical problems, such as a mailbox whose reputation has dropped. Alerts of the same kind are combined into one banner ("... on 3 mailboxes") with **View mailboxes** or **Show all**. The banners cover the last 7 days, and you can dismiss them. ## The date range **Last 7 days, Last 30 days** and **Last 90 days** control the health score, placement and charts. The default is 30 days. The picker is hidden while the dashboard is in its first-run state (below). ## Deliverability health The health score is a number from 0 to 100: how likely this mailbox's email is to reach the inbox instead of spam. The card shows the **average across your mailboxes for the range you selected**, a change compared with the previous period, and how many mailboxes and days it covers. Higher is better. The chart below plots the same score day by day, so its latest value is today's, not the range average. ## Inbox placement Where your **warmup** emails landed over the range: **Inbox**, **Spam** or **Bounced**, with the inbox rate as a percentage. This is warmup traffic between mailboxes, not your real campaigns. For where a real email lands, run a placement test from a mailbox (see [Troubleshooting](https://docs.warmerly.com/troubleshooting#placement-tests)). ## Today's sending Warmup emails sent so far today out of everything planned for today, added up across your mailboxes. Each mailbox runs on its own day and timezone, with a sending window of 8am to 8pm. Under it, a mix of your mailboxes: **Active**, **Warming** and **Paused**. This is warmup volume. Campaign sending is on the **Campaigns** pages. ## The three charts **Deliverability health**, **Inbox placement** and **Sending volume**, each over the selected range, one point per day. ## Mailboxes A table of up to 8 mailboxes, with the ones that need attention first, and **View all** to open **Accounts**. A badge shows how many need attention and links to those mailboxes. | Column | Meaning | | --- | --- | | **Status** | Healthy: sending well. Warming: still building trust with inbox providers. At Risk: showing warning signs, may need action. Paused: not sending right now. A line below explains why a mailbox is flagged. | | **Health score** | 0 to 100, as above, for this mailbox. | | **Daily limit** | How many warmup emails the mailbox may send today. It rises slowly and automatically as the mailbox gets healthier. See [How warmup works](https://docs.warmerly.com/how-warmup-works). | | **Actions** | The fix that fits: **Reconnect** (login expired), **Reactivate** (disconnected), **Review**, **Resume** (paused), or **View**. | A mailbox that is still warming up is not a problem: the note says "nothing to do yet". Click a row to open the mailbox. A mailbox that needs reconnecting opens its settings. See [Reconnect a mailbox](https://docs.warmerly.com/help/reconnect-mailbox). ## Workspace at a glance Cards for each part of the product, each linking to its page: - **Campaigns:** how many are active out of your total, emails sent and replies, with reply rate. - **Warmerly Link:** connected LinkedIn accounts, connections and messages sent, and acceptance rate. It reads "Not connected" until you add one. See [Plans & limits](https://docs.warmerly.com/plans-and-limits) for how LinkedIn is sold. - **Inbox:** unread conversations and how many are tracked. - **Email Finder:** emails found, batches and lookups, and how much of your allowance is used (or "Unlimited"). - **Verify:** valid and invalid emails and batches run, with allowance used. ## The first-run dashboard Until warmup has sent anything, the score, placement, charts and cards would all read zero. So on a brand-new account the Dashboard shows a **first-run** panel instead: - what is warming right now (your mailbox, or the free mailbox with its warmup day); - for the free mailbox, a reminder that it is for warmup, replies and tests, and that campaigns need your own connected mailbox or a OneMail mailbox; - a **Preview** of what each chart will show, in flat illustrative shapes, never made-up numbers. The normal charts return by themselves as soon as warmup has sent something. ## Common problems **Everything shows a dash or zero.** Warmup has not sent anything yet, or you have no mailbox. On a new account this is normal. Connect a mailbox, then give it a day. **"Couldn't load your warmup figures" (or mailboxes).** A request failed. Nothing has changed on your account. Refresh. If it repeats, check the [status page](https://docs.warmerly.com/help/status-page). **I cannot see a mailbox I expect.** Check that you are in the right workspace (see [Glossary](https://docs.warmerly.com/help/glossary#workspace)). The Dashboard lists mailboxes from every project in the selected workspace. **My health score is low.** See [Troubleshooting](https://docs.warmerly.com/troubleshooting): check DKIM, SPF and DMARC, run a placement test, and give a new mailbox time. ## Related - [Getting started checklist](https://docs.warmerly.com/help/getting-started-checklist) - [How warmup works](https://docs.warmerly.com/how-warmup-works) - [Glossary of Warmerly terms](https://docs.warmerly.com/help/glossary) --- # Guides Welcome! This section is here to help you get your email set up correctly, step by step, with no technical background needed. These guides are different from the **API Reference** section of our docs. The API Reference is written for developers who are connecting Warmerly to their own code. The guides on this page are written for everyone else, they walk you through the setup screens inside the Warmerly app itself, like proving you own your domain and connecting your mailbox, one click at a time. ## Available guides | Guide | What it covers | | --- | --- | | [Deliverability checklist before you launch](https://docs.warmerly.com/guides/deliverability-checklist) | Everything worth checking before your first campaign: DNS, mailboxes, warmup, list and copy. | | [Setting up DKIM](https://docs.warmerly.com/guides/dkim) | Adding one small code to your domain so your emails are marked as trustworthy and don't land in spam. | | [SPF & DMARC records](https://docs.warmerly.com/guides/spf-dmarc) | Two more codes that tell email providers "this email really is from us," which helps your emails get delivered. Per-host steps: [SPF](https://docs.warmerly.com/guides/spf/namecheap) / [DMARC](https://docs.warmerly.com/guides/dmarc/namecheap) on Namecheap, [SPF](https://docs.warmerly.com/guides/spf/godaddy) / [DMARC](https://docs.warmerly.com/guides/dmarc/godaddy) on GoDaddy, [SPF](https://docs.warmerly.com/guides/spf/cloudflare) / [DMARC](https://docs.warmerly.com/guides/dmarc/cloudflare) on Cloudflare, [SPF](https://docs.warmerly.com/guides/spf/ionos) / [DMARC](https://docs.warmerly.com/guides/dmarc/ionos) on IONOS. | | [Custom tracking domain](https://docs.warmerly.com/guides/custom-tracking-domain) | Using your own web address (instead of Warmerly's) for the links in your emails, so they look more professional and trustworthy. | | [Connecting a mailbox manually](https://docs.warmerly.com/guides/mailbox-connection) | Step-by-step instructions for linking your email account to Warmerly when the one-click connection option isn't available. | **Tip:** Start with DKIM and SPF & DMARC first. Those two guides cover the basic setup that every account needs. The other guides are for once you're up and running and want to fine-tune things. ## Still stuck? No worries: this stuff can be fiddly. If you get stuck on any step, click the chat help button in the bottom corner of the Warmerly app. It opens Warmi, our AI assistant, which can read your account and walk you through the fix. If it cannot solve it, it hands the conversation to a person on our support team. See [Warmi, the support assistant](https://docs.warmerly.com/help/warmi-support-assistant). --- # Email DNS records: the complete checklist Deliverability starts in DNS. Before warmup, before a single campaign, your sending domain needs a small set of records that tell Gmail, Outlook and everyone else that mail claiming to be from you really is from you. This page is the map: every record, what it does, and what Warmerly does and does not check. Each record also has a step-by-step guide of its own, linked below. ## The whole set, in one table | Record | Type | Name / host | Required? | What it does | | --- | --- | --- | --- | --- | | **MX** | MX | `@` (the domain itself) | Yes, to receive | Says which server accepts mail for the domain. Without it you cannot receive replies, and a domain that cannot receive mail is a red flag to spam filters. | | **SPF** | TXT | `@` | Yes | Lists the servers allowed to send as your domain. | | **DKIM** | TXT (sometimes CNAME) | `selector._domainkey` | Yes | Cryptographically signs your mail so a recipient can prove it was not altered or forged. | | **DMARC** | TXT | `_dmarc` | Yes | Tells receivers what to do when SPF and DKIM fail, and where to send reports. | | **Tracking CNAME** | CNAME | e.g. `track` | Optional | Serves open/click links on your own domain instead of Warmerly's. | | **BIMI** | TXT | `default._bimi` | Optional, advanced | Shows your logo beside your mail in supporting clients. Requires DMARC at enforcement and a VMC certificate. | One row needs emphasis because it is the one people skip: **your domain needs working MX records even if you only intend to send.** A sending-only domain with no inbound mail path looks disposable, and it means replies from the prospects you worked to win simply bounce. ## Do them in this order 1. **MX first.** Connect the mailbox at your provider and confirm mail arrives. Everything else authenticates mail from a mailbox that already works. 2. **SPF.** One TXT record at the root, listing your provider. See [SPF & DMARC](https://docs.warmerly.com/guides/spf-dmarc). 3. **DKIM.** Get the selector and key from your provider and publish it. See [Setting up DKIM](https://docs.warmerly.com/guides/dkim), plus click-by-click guides for [Namecheap](https://docs.warmerly.com/guides/dkim/namecheap), [IONOS](https://docs.warmerly.com/guides/dkim/ionos), [GoDaddy](https://docs.warmerly.com/guides/dkim/godaddy) and [Cloudflare](https://docs.warmerly.com/guides/dkim/cloudflare). 4. **DMARC, starting at `p=none`.** Monitor first, tighten later. See [SPF & DMARC](https://docs.warmerly.com/guides/spf-dmarc). 5. **Tracking CNAME**, if you want links on your own domain. See [Custom tracking domain](https://docs.warmerly.com/guides/custom-tracking-domain). 6. **Then warm up.** [How warmup works](https://docs.warmerly.com/how-warmup-works) explains why this order matters. ## What each record looks like ### SPF ``` Type: TXT Name: @ Value: v=spf1 include:_spf.google.com ~all ``` Exactly **one** SPF record per domain. Two SPF records is not twice the protection. It is a permanent error, and it is the single most common SPF mistake. If you send through more than one provider, merge them into one record with several `include:` terms. `~all` (softfail) is the sane default while you are setting things up; `-all` (hardfail) is stricter and worth moving to once you are certain every sender is listed. ### DKIM ``` Type: TXT Name: selector1._domainkey Value: v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GN... ``` The selector is whatever your provider tells you, `google`, `selector1`, `k1`, `zoho`, `onemail1`, something custom. Some providers (Microsoft 365, Mailchimp, Livemail) have you publish **CNAME** records pointing at their infrastructure instead of the TXT record itself; that is equally valid, and the public key lives on their side. ### DMARC ``` Type: TXT Name: _dmarc Value: v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com; fo=1 ``` Start at `p=none`. It changes nothing about delivery and starts the reports flowing, which is how you find out what is actually sending as your domain before you tell the world to reject it. Move to `p=quarantine`, then `p=reject`, once those reports are clean. ### MX ``` Type: MX Name: @ Value: (your provider's host, e.g. aspmx.l.google.com) Priority: 1 ``` Use your provider's published list, in their priority order. Do not mix MX records from two mail providers on one domain. ### Tracking CNAME ``` Type: CNAME Name: track Value: (the target Warmerly shows you) ``` Then wait for the certificate to finish issuing, the [tracking domain guide](https://docs.warmerly.com/guides/custom-tracking-domain) covers that wait, which catches people out. ## What Warmerly actually checks Warmerly runs its own DNS check per mailbox domain and shows it on the mailbox, and the same check drives campaign readiness. It looks at three of the records above, **SPF, DKIM and DMARC**: and reports each as `pass`, `none`, `fail` or `error`: | Status | Meaning | | --- | --- | | `pass` | The record was found and looks valid. | | `none` | No record found at all. | | `fail` | Found but broken, for SPF, the usual cause is **two SPF records** on one domain. | | `error` | DNS itself did not answer (a timeout or a resolver problem), not a verdict about your records. Re-check. | Two limits are worth knowing, because both produce a scary-looking result on a domain that is genuinely fine: - **DKIM selectors are guessed.** Warmerly tries a long list of common selector names (`default`, `google`, `selector1`, `k1`, `zoho`, `onemail1`, and many more). It cannot discover an arbitrary custom selector. If yours is not on that list the check reports `none` while your mail is signed perfectly well, enter your real selector on the mailbox (**Accounts → the mailbox → Settings → DKIM selector**) and re-check. Full explanation in [Troubleshooting](https://docs.warmerly.com/troubleshooting). - **MX and the tracking CNAME are checked elsewhere.** A green SPF/DKIM/DMARC panel is not a statement about your MX records. Over the API the same data is available as [`GET /accounts/{id}/dns`](https://docs.warmerly.com/accounts#dns-and-domain-checks), and `POST /accounts/{id}/dns` re-runs the check on demand. ## After you save a record - **Propagation takes minutes, occasionally hours.** Your DNS host's TTL decides it. Re-check rather than re-adding; a duplicate record is worse than a slow one. - **Check the name your host actually saved.** Many control panels append the domain automatically, so typing `selector1._domainkey.yourdomain.com` produces `selector1._domainkey.yourdomain.com.yourdomain.com`. If the record will not resolve, this is the first thing to look at. - **Quote the value if your host requires it**, and never break a long DKIM key across lines yourself. - **Check the domain, not the subdomain.** Mail DNS for `mail@yourdomain.com` lives on `yourdomain.com`, not on `www.yourdomain.com`. ## Common mistakes, in the order we see them 1. Two SPF records on one domain (reports `fail`). 2. A custom DKIM selector Warmerly cannot guess (reports `none`, mail is fine). 3. The host silently appending the domain to the record name. 4. No DMARC record at all: the easiest win on this page, and `p=none` costs nothing. 5. No MX records on a send-only domain, so every reply bounces. 6. A DMARC policy tightened to `p=reject` before the reports were read, which starts rejecting legitimate mail from a tool nobody remembered was sending as the domain. ## Check it from outside You can check any domain's setup (yours or a prospect's) with the public [deliverability checker](https://warmerly.com/deliverability-checker), which runs the same SPF/DKIM/DMARC logic and needs no account. Programmatically that is `POST /api/v1/public/deliverability-check`, the one endpoint in the API that takes no credentials (10 requests per hour per IP, see [Errors & rate limits](https://docs.warmerly.com/errors)). ## Related - [Setting up DKIM](https://docs.warmerly.com/guides/dkim) · [SPF & DMARC](https://docs.warmerly.com/guides/spf-dmarc) · [Custom tracking domain](https://docs.warmerly.com/guides/custom-tracking-domain) - [Connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection): SMTP/IMAP settings, app passwords, Microsoft 365 errors - [Troubleshooting](https://docs.warmerly.com/troubleshooting): when a record exists but Warmerly disagrees --- # What Is DKIM? (And How to Set It Up) This guide explains DKIM in plain English and walks you through fixing it if Warmerly says it's missing. No technical background needed. ## What is DKIM? DKIM stands for **DomainKeys Identified Mail**. It's a small, invisible stamp added to every email you send. That stamp proves the email really came from your domain and wasn't faked or tampered with along the way. Think of it like a wax seal on a letter. Anyone can write a letter and sign your name at the bottom, but a wax seal with your actual stamp is much harder to fake. DKIM works the same way for email. Why this matters for you: - **It helps your emails avoid the spam folder.** Mailbox providers like Gmail and Outlook check for DKIM. Emails without it look more suspicious and are more likely to get filtered out. - **It protects your reputation.** DKIM makes it harder for scammers to send fake emails that look like they're from your business. - **It's required for good deliverability.** If you're sending cold outreach or warming up a new mailbox, DKIM is one of the basic things every mailbox provider expects to see. DKIM lives in your domain's **DNS** settings. DNS (Domain Name System) is basically your domain's address book, it's the place where you point your domain name to your website, your email provider, and other services. Your DNS is managed wherever you bought or host your domain (for example, Namecheap, GoDaddy, IONOS, or Cloudflare). ## Step 1: Let Warmerly check it for you first You don't need to do anything manually right away. The moment you connect a mailbox to Warmerly, we automatically check your domain's DNS for DKIM. We test it against a long list of the most common setups used by email providers like Google Workspace, Microsoft 365, Mailgun, SendGrid, Zoho, and many others. **If Warmerly shows a green "DKIM found" status, you're done.** Nothing else to do — your domain is already set up correctly. You only need to keep reading if Warmerly shows **"DKIM not found."** ## Step 2: If DKIM is not found, get your DKIM record Every email provider (Google, Microsoft, Mailgun, etc.) has its own page where it gives you a DKIM record to add. This record has two parts: 1. **A selector**: a short name, like `google` or `s1`. Think of it as a label for this specific DKIM record. 2. **A value**: a long string of random-looking letters and numbers. This is the actual "key" that proves emails are from you. Here's how to find yours: 1. Log in to your email provider's dashboard (for example, Google Workspace Admin Console, or your Mailgun/SendGrid account). 2. Look for a setting called **DKIM**, **DomainKeys**, or **Email Authentication**. 3. Generate or view the DKIM record. The provider will show you something you need to add as a **TXT record**: TXT just means a plain-text entry in your DNS. 4. Copy both the selector name and the long value. You'll need to paste these into your domain's DNS settings next. **Every provider calls this something slightly different and puts it in a different place in their dashboard.** If you're not sure where to look, search your provider's help center for "DKIM setup" plus your provider's name. ## Step 3: Add the record at your domain's DNS host Now go to wherever your domain's DNS is managed. This is usually the company you bought your domain from, not your email provider. 1. Log in to your domain host's dashboard. 2. Find the **DNS** or **DNS Records** section. 3. Add a new **TXT record** using the selector and value your email provider gave you in Step 2. 4. Save the record. **DNS changes can take anywhere from a few minutes to a few hours to go live** — this is normal and just how the internet works. Don't panic if Warmerly still shows "not found" right away; check back later. ## Step 4: If Warmerly still doesn't detect it, add the selector manually Warmerly automatically checks dozens of common selector names. If your provider used one of those, Warmerly will find your new record on its own, no further action needed. But some providers use a custom or unusual selector name that Warmerly doesn't check by default. If that happens: 1. In Warmerly, go to **Accounts**. 2. Click into the mailbox you're setting up. 3. Go to **Settings**. 4. Find the **DKIM selector** field and enter your selector. **The selector is just the part of the DNS record name before `._domainkey.yourdomain.com`.** For example, if your DNS record is named `google._domainkey.yourdomain.com`, your selector is simply `google`. Your email provider's DKIM setup page will show you this name, you just need the first part. ## Step 5: Need exact click-by-click steps for your DNS host? If you're not sure how to add a TXT record at your specific domain host, we have step-by-step guides with screenshots for the most common ones: | DNS host | Guide | | --- | --- | | Namecheap | [Set up DKIM on Namecheap](https://docs.warmerly.com/guides/dkim/namecheap) | | IONOS | [Set up DKIM on IONOS](https://docs.warmerly.com/guides/dkim/ionos) | | GoDaddy | [Set up DKIM on GoDaddy](https://docs.warmerly.com/guides/dkim/godaddy) | | Cloudflare | [Set up DKIM on Cloudflare](https://docs.warmerly.com/guides/dkim/cloudflare) | ## One more thing: SPF and DMARC DKIM is one of three email-security records that work together. The other two are **SPF** (Sender Policy Framework) and **DMARC** (Domain-based Message Authentication, Reporting, and Conformance). In short, SPF lists which servers are allowed to send email for your domain, and DMARC tells mailbox providers what to do if an email fails these checks. We cover both of those, with the same plain-English approach, in a separate guide: [SPF and DMARC explained](https://docs.warmerly.com/guides/spf-dmarc). --- # Set Up DKIM on Namecheap **DKIM** (short for DomainKeys Identified Mail) is a small, invisible stamp added to your emails that proves they really came from your domain. If you want the full plain-English explanation of what it is and why it matters, read [What Is DKIM?](https://docs.warmerly.com/guides/dkim) first. This page only covers the exact clicks needed if your domain is registered or hosted at **Namecheap**. Before you start, you'll need the DKIM record your email provider (for example, Google Workspace, Namecheap Private Email, Microsoft 365, or another email service) gave you. That record has two parts: a **selector** (a short name like `google` or `s1`) and a **value** (a long string of letters and numbers). If you don't have these yet, go back to your email provider's DKIM or "Email Authentication" settings and copy them first. ## Step 1: Log in to Namecheap 1. Go to [namecheap.com](https://www.namecheap.com) and sign in to your account. 2. Once logged in, click **Domain List** in the left-hand menu. 3. Find the domain you're setting up and click the **Manage** button next to it. ## Step 2: Open Advanced DNS 1. On the domain's management page, click the **Advanced DNS** tab near the top. 2. This is where all of your domain's **DNS** records live. DNS (Domain Name System) is basically your domain's address book. It's what tells the internet where your website and email actually live. ## Step 3: Add a new TXT record 1. Scroll down to the **Host Records** section. 2. Click the **Add New Record** button. 3. For **Type**, choose **TXT Record** from the dropdown. 4. For **Host**, enter your DKIM selector followed by `._domainkey`, for example, if your selector is `google`, enter: ``` google._domainkey ``` 5. For **Value**, paste the long DKIM value your email provider gave you. 6. For **TTL**, you can leave it on **Automatic** (or `3600` if you're asked to pick a number), this just controls how often the record refreshes and doesn't need changing. 7. Click the green checkmark to save the row, then click **Save All Changes** at the bottom of the page. **Important: only enter the selector part in the Host field, not your full domain name.** Namecheap automatically adds `.yourdomain.com` to whatever you type in Host. So if you type `google._domainkey.yourdomain.com` (with your domain included), Namecheap will end up creating `google._domainkey.yourdomain.com.yourdomain.com`, which is wrong and won't work. Just type `google._domainkey` and let Namecheap handle the rest. | Field | What to enter | | --- | --- | | Type | TXT Record | | Host | `._domainkey` (for example, `google._domainkey`), not the full domain | | Value | The long DKIM value from your email provider | | TTL | Automatic (or `3600`) | ## Step 4: Tell Warmerly your selector (if needed) Warmerly automatically checks your domain against a long list of common DKIM selector names. If your provider used a common one, Warmerly will find your new record on its own, you can skip this step. If Warmerly still shows **"DKIM not found"** after you've added the record and waited a bit, enter your selector manually: 1. In Warmerly, go to **Accounts**. 2. Click into the mailbox you're setting up. 3. Go to **Settings**. 4. Find the **DKIM selector** field and type in the selector you used above (for example, just `google`, without the `._domainkey` part). ## Step 5: Be patient. DNS takes time **DNS changes can take anywhere from a few minutes up to 24–48 hours to fully take effect**, even though Namecheap itself usually updates within about 30 minutes. This is normal, it's how DNS works everywhere, not just on Namecheap. If Warmerly doesn't show "DKIM found" right away, don't worry. Add the record, save it, and check back later. Still stuck? Click the chat help button in the bottom corner of the Warmerly app to talk to a real person on our support team. --- # Set up DKIM on IONOS **DKIM** (short for **DomainKeys Identified Mail**) is a small, invisible stamp added to every email you send. It proves the email really came from your domain and wasn't faked along the way. If you haven't already, read our main [DKIM guide](https://docs.warmerly.com/guides/dkim) first, it explains what DKIM is and why it matters, in plain English. This page just covers the exact clicks for IONOS, one of the most common places people manage their domain. ## Step 1: Get your DKIM record from your email provider Before you touch IONOS, you need two things from your email provider (Google Workspace, Microsoft 365, Mailgun, SendGrid, Zoho, or whichever one sends your mail): 1. A **selector**: a short label, like `google` or `s1`. 2. A **value**: a long string of letters and numbers. Your email provider's admin dashboard will show you these under a setting called **DKIM**, **DomainKeys**, or **Email Authentication**. Copy both — you'll paste them into IONOS in Step 3. ## Step 2: Log in and find your domain's DNS settings 1. Go to [my.ionos.com](https://my.ionos.com) and log in with your IONOS account. 2. Find the domain you want to update in your list of domains. 3. Click the gear icon (⚙) next to that domain, under **Actions**. 4. Select **DNS** from the menu that appears. **Note:** IONOS has changed its panel layout over the years. If you don't see a gear icon, look for **Domains & SSL** in the main menu, click your domain, then look for a **DNS** or **DNS settings** tab. Some older IONOS accounts still call this the "Domain Center", the DNS section works the same way either way. ## Step 3: Add a new TXT record A **TXT record** is just a plain-text entry in your domain's DNS, think of DNS as your domain's address book, and a TXT record as one more line written into it. 1. On the DNS settings page, click **Add Record**. 2. From the **Type** dropdown, choose **TXT**. 3. In the **Host name** field, enter your DKIM selector followed by `._domainkey`. For example, if your selector is `google`, enter `google._domainkey`. (Your email provider's instructions will usually spell out this full host name for you, if they do, just copy theirs exactly.) 4. In the **Value** field, paste the long DKIM value your email provider gave you. 5. Leave **TTL** on its default setting unless your provider told you to change it. 6. Click **Save**. That's it: your TXT record is now saved in IONOS. | Field | What to enter | | --- | --- | | Type | TXT | | Host name | Your selector + `._domainkey` (e.g. `google._domainkey`) | | Value | The long DKIM value from your email provider | | TTL | Default is fine | **Double-check for typos before saving.** A single missing character in the value field will make DKIM fail even though the record looks like it saved correctly. If you're copying and pasting, make sure no extra spaces or line breaks got added at the start or end. ## Step 4: Tell Warmerly your selector IONOS is a common host for domains where the email provider uses a **custom DKIM selector**: one that Warmerly doesn't automatically check for. This is exactly why Warmerly has a manual selector field: so you can tell us the exact selector your provider used, instead of waiting on us to guess it. To add it: 1. In Warmerly, go to **Accounts**. 2. Click into the mailbox you just set up DKIM for. 3. Go to **Settings**. 4. Find the **DKIM selector** field and type in your selector (just the short label, like `google`, not the full `._domainkey.yourdomain.com` part). 5. Save. Warmerly will now check specifically for the record you added, instead of only the common defaults. ## Step 5: Wait for it to go live **DNS changes can take up to 24–48 hours to fully take effect**, even though IONOS usually applies the change on its end right away. This delay isn't a bug, it's just how the internet spreads DNS updates around the world. If Warmerly still shows "DKIM not found" a few minutes after you save the record, that's normal. Check back later, and it should update on its own once the change has spread. If it's still showing as missing after two full days, double-check the host name and value in IONOS for typos, and confirm the selector you entered in Warmerly matches exactly. --- # Set Up DKIM on GoDaddy **DKIM** (short for DomainKeys Identified Mail) is a small, hidden stamp added to your emails that proves they really came from your domain. If you landed here, you probably already have a DKIM selector and value from your email provider, and now you need to add them to your domain's settings on GoDaddy. If you're not sure what DKIM is or where to get your selector and value, start with the main guide first: [What Is DKIM? (And How to Set It Up)](https://docs.warmerly.com/guides/dkim). This guide shows you exactly where to click in GoDaddy to add the record. ## What you'll need before you start - Your GoDaddy username and password (or the account that manages your domain). - The **selector** and **value** your email provider gave you (for example, from Google Workspace, Microsoft 365, Mailgun, or SendGrid). See Step 2 of the [main DKIM guide](https://docs.warmerly.com/guides/dkim) if you don't have these yet. ## Step 1: Log in to GoDaddy 1. Go to [godaddy.com](https://www.godaddy.com) and click **Sign In** in the top right corner. 2. Enter your username and password. 3. If GoDaddy asks for a one-time code (this happens if you have extra security turned on for your account), check your email or authenticator app and enter it. ## Step 2: Find your domain's DNS settings 1. Once you're logged in, click **My Products** (usually in the top menu, or under your account icon). 2. Find the domain you want to update in your list of domains, and click on it. This opens the domain's settings page. 3. Look for a button or tab called **DNS**. Click it. This takes you to the **DNS Management** page (sometimes called **Manage DNS**) for that domain. This is where all of your domain's **DNS** records live. DNS (short for Domain Name System) is like your domain's address book. It tells the internet where to send your website traffic, your email, and other services. ## Step 3: Add a new TXT record DKIM records are added as a **TXT record**. A TXT record is just a plain-text entry in your DNS that other services can read. 1. On the DNS Management page, click **Add New Record** (sometimes shown as just **Add**). 2. From the **Type** dropdown, choose **TXT**. 3. In the **Name** (sometimes called **Host**) field, enter your selector followed by `._domainkey`. For example, if your email provider gave you the selector `google`, type: ``` google._domainkey ``` **Do not type your full domain name here.** GoDaddy automatically adds your domain name to the end, so typing the full domain (like `google._domainkey.yourdomain.com`) will create the wrong record. Just enter the selector part plus `._domainkey`. 4. In the **Value** field, paste the long string of letters and numbers your email provider gave you. This is often called the DKIM key. Paste it exactly as given, don't add extra spaces or line breaks. 5. Leave **TTL** (Time to Live) set to the default. TTL just controls how often other computers double-check this record; the default works fine. 6. Click **Save** (or **Save All Records** if you're adding more than one record at the same time). That's it: GoDaddy now has your DKIM record saved. | Field | What to enter | | --- | --- | | Type | `TXT` | | Name / Host | `._domainkey` (for example, `google._domainkey`) | | Value | The long key value your email provider gave you | | TTL | Leave as default | ## Step 4: Add the selector to Warmerly, if needed Warmerly automatically checks for dozens of common DKIM selector names, so in most cases it will find your new record on its own, no further action needed. If Warmerly still shows "DKIM not found" after you've added the record and waited a while (see the timing note below), your provider may use a selector name Warmerly doesn't check by default. In that case: 1. In Warmerly, go to **Accounts**. 2. Click into the mailbox you're setting up. 3. Go to **Settings**. 4. Find the **DKIM selector** field and type in your selector, just the short name (like `google`), not the full record name. ## A note on timing **DNS changes are not instant.** After you save a new TXT record in GoDaddy, it can take anywhere from a few minutes up to **24-48 hours** to fully take effect everywhere on the internet. This is normal. If Warmerly still shows "DKIM not found" right after you save the record, don't worry, check back in a few hours, and again the next day if needed. ## Still stuck? Head back to the main guide for more on troubleshooting and on the two other email-security records that work alongside DKIM, **SPF** and **DMARC**: [What Is DKIM? (And How to Set It Up)](https://docs.warmerly.com/guides/dkim). --- # Set Up DKIM on Cloudflare **DKIM** (short for **DomainKeys Identified Mail**) is a small stamp added to your emails that proves they really came from your domain. If Warmerly told you your DKIM is missing and your domain's **DNS** (Domain Name System, the settings that control where your domain points) is managed in Cloudflare, this guide shows you exactly where to click. For the full explanation of what DKIM is and why it matters, see [What Is DKIM?](https://docs.warmerly.com/guides/dkim). Before you start, make sure you already have your DKIM **selector** (a short label, like `google` or `s1`) and your DKIM **value** (a long string of letters and numbers). Your email provider (Google Workspace, Microsoft 365, Mailgun, SendGrid, etc.) gives you these two things. If you don't have them yet, go back to [Step 2 of the DKIM guide](https://docs.warmerly.com/guides/dkim#step-2-if-dkim-is-not-found-get-your-dkim-record) first. ## Step 1: Log in to Cloudflare 1. Go to [dash.cloudflare.com](https://dash.cloudflare.com) and log in. 2. On the main dashboard, click the domain (Cloudflare calls it a **site**) that you use to send email, for example, `yourbusiness.com`. ## Step 2: Open the DNS Records tab 1. Once you're inside your site, look at the left-hand menu. 2. Click **DNS**, then click **Records**. This page lists every DNS entry for your domain, things like your website's address and your existing email settings. ## Step 3: Add a new TXT record A **TXT record** is just a plain-text entry in your DNS. This is the type of record DKIM uses. 1. Click the **Add record** button. 2. For **Type**, choose **TXT** from the dropdown. 3. For **Name**, enter your DKIM selector followed by `._domainkey`. For example, if your selector is `google`, enter `google._domainkey`. Your email provider's instructions will usually show you this full name already. You can copy it directly. 4. For **Content**, paste the long DKIM value your email provider gave you. Paste it exactly as given, with no extra spaces or line breaks. 5. Leave **TTL** (Time to Live: how often the record refreshes) set to **Auto**. 6. Click **Save**. ## Important: turn the proxy off for this record Cloudflare shows a small cloud icon next to every DNS record. This icon can be either: - **Orange cloud (Proxied)**: Cloudflare routes traffic through its own servers first. This is normally used for websites, not email. - **Grey cloud (DNS only)**: the record points directly to its destination, with no extra routing in between. **Your new TXT record must be set to grey cloud (DNS only), not orange (Proxied).** Email programs read DKIM records directly and don't understand Cloudflare's proxy. If the record is proxied, mailbox providers like Gmail and Outlook won't be able to verify it, and your DKIM check will keep failing. TXT records are usually grey by default and don't show a cloud toggle at all, since proxying only applies to certain record types (like A and CNAME, a CNAME record points one domain name to another). Still, it's worth double-checking the record right after you save it. If you see a cloud icon next to it, click it once so it turns grey before moving on. ## Step 4: Wait, then check Warmerly Warmerly automatically rechecks your domain in the background. You don't need to click anything else on our side unless a manual step below applies to you. ## Step 5: If Warmerly still shows "not found," add the selector manually Warmerly checks dozens of common selector names automatically. If it still can't find your record after your DNS change has had time to go live, add the selector by hand: 1. In Warmerly, go to **Accounts**. 2. Click into the mailbox you're setting up. 3. Go to **Settings**. 4. Find the **DKIM selector** field and enter your selector (just the short label, like `google`, not the full `._domainkey.yourdomain.com` part). ## A note on timing DNS changes can take up to **24-48 hours** to fully take effect everywhere on the internet. In practice, Cloudflare is one of the fastest DNS hosts around, changes often show up within a few minutes to an hour. If Warmerly still shows "DKIM not found" right after you save the record, don't worry. Check back a little later before troubleshooting further. --- # What Are SPF & DMARC? (And How to Set Them Up) This guide explains SPF and DMARC in plain English and walks you through adding them to your domain. No technical background needed. ## What is SPF? SPF stands for **Sender Policy Framework**. It's a short list, stored in your domain's **DNS**, of which mail servers are allowed to send email for your domain. DNS (Domain Name System) is your domain's address book, the place where you point your domain name to your website, your email provider, and other services. Your DNS is managed wherever you bought or host your domain (for example, Namecheap, GoDaddy, IONOS, or Cloudflare). Think of SPF like a guest list at a door. When an inbox provider like Gmail or Outlook receives an email claiming to be from `yourdomain.com`, it checks your SPF list to see if the server that actually sent the email is allowed to. If the sending server isn't on the list, that's a red flag. ## What is DMARC? DMARC stands for **Domain-based Message Authentication, Reporting, and Conformance**. It's a second DNS record that tells inbox providers two things: 1. **What to do** if an email claiming to be from your domain fails your SPF or DKIM checks (DKIM is a separate email-security stamp, more on that below). Should the inbox provider deliver it anyway, send it to spam, or reject it outright? 2. **Where to send reports**: a summary email address where inbox providers will tell you how many messages passed or failed your checks, and who sent them. ## Why both matter - **They help your emails land in the inbox instead of spam.** Gmail, Outlook, and other major inbox providers check for SPF and DMARC. Domains without them look more suspicious, and that hurts delivery, even for emails you send yourself. - **They stop other people from faking emails as "you."** Without SPF and DMARC, scammers can send emails that claim to be from your domain, and inbox providers have no easy way to tell the difference. - **They're expected for good deliverability.** If you're doing cold outreach or warming up a new mailbox, SPF and DMARC are basic setup that every inbox provider expects to see, alongside DKIM. ## How SPF, DKIM, and DMARC work together These are three separate DNS records, and they each do a different job: | Record | What it does | | --- | --- | | SPF | Lists which mail servers are allowed to send email for your domain. | | DKIM | Adds an invisible, tamper-proof stamp to each email proving it really came from you. | | DMARC | Tells inbox providers what to do if a message fails SPF or DKIM, and where to send reports. | They work as a team. SPF and DKIM are the two checks an email can pass or fail. DMARC is the rulebook that says what happens next. You want all three set up. We cover DKIM, including how to set it up, in a separate guide: [Setting up DKIM](https://docs.warmerly.com/guides/dkim). ## SPF and DMARC don't need a "selector" If you've already read the DKIM guide, you'll know DKIM records have two parts: a **selector** (a short label, like `google`) and a long value. That's because a domain can have several different DKIM records at once, each with its own selector, so mailbox providers need a way to tell them apart. SPF and DMARC are simpler. **Each one is just a single TXT record, and it always lives at your root domain**: you don't add a selector name to the front of it. A TXT record is just a plain-text entry in your DNS. You'll add: - One SPF TXT record at `yourdomain.com` - One DMARC TXT record at `_dmarc.yourdomain.com` That's it: no selector to look up or configure, and no separate setting inside Warmerly for these two. ## Where to add these records at your DNS host The SPF and DMARC records go in the exact same place as your DKIM record, same DNS panel, same overall process. Only the record type and value are different. If you're not sure how to get into your DNS settings, follow the click-by-click DKIM guide for your host below, then repeat the same steps for your SPF and DMARC records. | DNS host | Where to add records | SPF | DMARC | DKIM | | --- | --- | --- | --- | --- | | Namecheap | **Advanced DNS** tab on your domain | [SPF on Namecheap](https://docs.warmerly.com/guides/spf/namecheap) | [DMARC on Namecheap](https://docs.warmerly.com/guides/dmarc/namecheap) | [DKIM on Namecheap](https://docs.warmerly.com/guides/dkim/namecheap) | | IONOS | **DNS settings** under **Domains & SSL** | [SPF on IONOS](https://docs.warmerly.com/guides/spf/ionos) | [DMARC on IONOS](https://docs.warmerly.com/guides/dmarc/ionos) | [DKIM on IONOS](https://docs.warmerly.com/guides/dkim/ionos) | | GoDaddy | **DNS Management** page for your domain | [SPF on GoDaddy](https://docs.warmerly.com/guides/spf/godaddy) | [DMARC on GoDaddy](https://docs.warmerly.com/guides/dmarc/godaddy) | [DKIM on GoDaddy](https://docs.warmerly.com/guides/dkim/godaddy) | | Cloudflare | **DNS > Records** tab | [SPF on Cloudflare](https://docs.warmerly.com/guides/spf/cloudflare) | [DMARC on Cloudflare](https://docs.warmerly.com/guides/dmarc/cloudflare) | [DKIM on Cloudflare](https://docs.warmerly.com/guides/dkim/cloudflare) | Each host now has its own click-by-click SPF and DMARC guide, with the exact name and value to enter. ## What a typical SPF record looks like An SPF record is a TXT record added at your root domain (just `yourdomain.com`, no prefix). For example, if you send email through Google Workspace, it might look like this: ``` v=spf1 include:_spf.google.com ~all ``` In plain English, this just means **"allow Google's mail servers to send email for me."** Breaking it down: - `v=spf1`: this is an SPF record, version 1. - `include:_spf.google.com`: trust the list of servers Google maintains for its customers. - `~all`: treat anything not on this list as suspicious (but don't hard-reject it). If you send from more than one provider (say, Google Workspace and a cold-outreach tool), you'll have one SPF record with multiple `include:` parts, not one record per provider. Adding two separate SPF records breaks SPF entirely, always combine them into a single record. ## What a typical starter DMARC record looks like A DMARC record is a TXT record added at `_dmarc.yourdomain.com` (note the `_dmarc.` prefix, this one is not at the bare root domain). A safe starting point looks like this: ``` v=DMARC1; p=none; rua=mailto:you@yourdomain.com ``` In plain English: - `v=DMARC1`: this is a DMARC record, version 1. - `p=none`: **just watch and report, don't reject or quarantine anything yet.** This is the safest way to start, especially if you're not 100% sure every one of your sending servers is covered by SPF yet. - `rua=mailto:you@yourdomain.com`: send daily summary reports to this email address, so you can see what's passing and what isn't. Once you've watched your reports for a few weeks and everything looks clean, you can tighten `p=none` to `p=quarantine` (send failures to spam) or `p=reject` (block them outright). **Don't jump straight to `p=reject`**: if your SPF record is missing a sending server, you could accidentally block your own legitimate emails. ## Check your provider's exact recommended value The examples above use Google Workspace, but your SPF `include:` value will be different if you send through Microsoft 365, Mailgun, SendGrid, Zoho, or another provider. **Always check your email provider's own help docs for their exact recommended SPF include value**: search their help center for "SPF record setup" plus your provider's name. The DMARC record format, on the other hand, is the same no matter which email provider you use. ## Still stuck? If you get stuck on any step, click the chat help button in the bottom corner of the Warmerly app. It connects you straight to a real person on our support team who can look at your account and help you sort it out. --- # Set Up an SPF Record on Namecheap An **SPF record** is a single TXT record that lists which mail servers may send email for your domain. This guide shows exactly where to add it in Namecheap. If you want the background first, read [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). ## What you'll need - The SPF **include** value from your email provider. For Google Workspace it is `include:_spf.google.com`; for Microsoft 365 it is `include:spf.protection.outlook.com`. Check your provider's help page for the exact value if you use another service. - Access to the domain's DNS in Namecheap. ## Step 1: Open your domain's DNS in Namecheap 1. Go to [namecheap.com](https://www.namecheap.com) and sign in. 2. Click **Domain List** in the left-hand menu, find your domain, and click **Manage**. 3. Open the **Advanced DNS** tab. The **Host Records** section lists every DNS record on the domain. ## Step 2: Add the SPF TXT record 1. Click **Add New Record** and choose **TXT Record** as the type. 2. In the **Host** field: Enter `@` (this means the root domain, `yourdomain.com`). Some panels leave the field blank for the root instead. Never type the full domain name here. 3. In the **Value** field: Paste your SPF value, for example `v=spf1 include:_spf.google.com ~all`. 4. Leave **TTL** on **Automatic**. 5. Click the green checkmark to save the row, then **Save All Changes**. | Field | What to enter | | --- | --- | | Type | `TXT` | | Host | `@` | | Value | `v=spf1 include:_spf.google.com ~all` | ## If you already have an SPF record A domain can only have **one** SPF record. If Namecheap already shows a TXT record starting with `v=spf1`, **edit that record** and add your new `include:` before the `~all` at the end. Adding a second SPF record breaks SPF for the whole domain, so mail starts failing authentication. For example, to send from Google Workspace and another tool, combine them into one record: ``` v=spf1 include:_spf.google.com include:spf.mailprovider.com ~all ``` SPF also allows at most 10 DNS lookups across all your `include:` entries. If you go over, SPF fails with a "permerror". ## Step 3: Check SPF in Warmerly Warmerly rechecks your domain's DNS automatically. DNS changes can take anywhere from a few minutes up to 24 to 48 hours to spread, so if the SPF warning is still showing right after you save, check again later. You do not need a selector for SPF, because it is one record at a fixed location. ## Still stuck? Back to the main guide: [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). The same click-path in Namecheap is used for [DKIM](https://docs.warmerly.com/guides/dkim/namecheap). To see what is live right now, use the free [SPF checker](https://warmerly.com/spf-checker) or [DMARC checker](https://warmerly.com/dmarc-checker). --- # Set Up a DMARC Record on Namecheap A **DMARC record** is a TXT record at `_dmarc.yourdomain.com` that tells inbox providers what to do with mail that fails SPF or DKIM, and where to send reports. This guide shows exactly where to add it in Namecheap. For the background, read [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). ## What you'll need - A mailbox address to receive DMARC reports, for example `dmarc@yourdomain.com`. - SPF and DKIM already set up for your sending domain. See [SPF on Namecheap](https://docs.warmerly.com/guides/spf/namecheap) and [DKIM on Namecheap](https://docs.warmerly.com/guides/dkim/namecheap). DMARC checks them, so it is only useful once they pass. ## Step 1: Open your domain's DNS in Namecheap 1. Go to [namecheap.com](https://www.namecheap.com) and sign in. 2. Click **Domain List** in the left-hand menu, find your domain, and click **Manage**. 3. Open the **Advanced DNS** tab. The **Host Records** section lists every DNS record on the domain. ## Step 2: Add the DMARC TXT record 1. Click **Add New Record** and choose **TXT Record** as the type. 2. In the **Host** field: Enter `_dmarc` only. Namecheap adds your domain to the end automatically, so typing `_dmarc.yourdomain.com` would create the wrong record. 3. In the **Value** field: Paste `v=DMARC1; p=none; rua=mailto:you@yourdomain.com`, using your own report address. 4. Leave **TTL** on **Automatic**. 5. Click the green checkmark to save the row, then **Save All Changes**. | Field | What to enter | | --- | --- | | Type | `TXT` | | Host | `_dmarc` | | Value | `v=DMARC1; p=none; rua=mailto:you@yourdomain.com` | ## Start with p=none, then tighten `p=none` only watches and reports. It is the safe way to start because it cannot block any of your own mail. After a few weeks of clean reports, move to `p=quarantine` (send failures to spam) and later `p=reject` (block them). Jumping straight to `p=reject` risks blocking legitimate mail if an SPF include is missing. ## If you already have a DMARC record A domain can only have **one** DMARC record. If Namecheap already lists a TXT record at `_dmarc`, edit it instead of adding another. ## Step 3: Check DMARC in Warmerly Warmerly rechecks your domain's DNS automatically. DNS changes can take anywhere from a few minutes up to 24 to 48 hours to spread, so if the DMARC warning is still showing right after you save, check again later. You do not need a selector for DMARC, because it is one record at a fixed location. ## Still stuck? Back to the main guide: [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). The same click-path in Namecheap is used for [DKIM](https://docs.warmerly.com/guides/dkim/namecheap). To see what is live right now, use the free [SPF checker](https://warmerly.com/spf-checker) or [DMARC checker](https://warmerly.com/dmarc-checker). --- # Set Up an SPF Record on GoDaddy An **SPF record** is a single TXT record that lists which mail servers may send email for your domain. This guide shows exactly where to add it in GoDaddy. If you want the background first, read [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). ## What you'll need - The SPF **include** value from your email provider. For Google Workspace it is `include:_spf.google.com`; for Microsoft 365 it is `include:spf.protection.outlook.com`. Check your provider's help page for the exact value if you use another service. - Access to the domain's DNS in GoDaddy. ## Step 1: Open your domain's DNS in GoDaddy 1. Go to [godaddy.com](https://www.godaddy.com) and sign in. 2. Open **My Products**, find your domain, and click **DNS** (sometimes shown as **Manage DNS**). 3. You are now on the **DNS Management** page, where the domain's records are listed. ## Step 2: Add the SPF TXT record 1. Click **Add New Record** (or **Add**) and choose **TXT** as the type. 2. In the **Name** field: Enter `@` (this means the root domain, `yourdomain.com`). Some panels leave the field blank for the root instead. Never type the full domain name here. 3. In the **Value** field: Paste your SPF value, for example `v=spf1 include:_spf.google.com ~all`. 4. Leave **TTL** on its default. 5. Click **Save**. | Field | What to enter | | --- | --- | | Type | `TXT` | | Name | `@` | | Value | `v=spf1 include:_spf.google.com ~all` | ## If you already have an SPF record A domain can only have **one** SPF record. If GoDaddy already shows a TXT record starting with `v=spf1`, **edit that record** and add your new `include:` before the `~all` at the end. Adding a second SPF record breaks SPF for the whole domain, so mail starts failing authentication. For example, to send from Google Workspace and another tool, combine them into one record: ``` v=spf1 include:_spf.google.com include:spf.mailprovider.com ~all ``` SPF also allows at most 10 DNS lookups across all your `include:` entries. If you go over, SPF fails with a "permerror". ## Step 3: Check SPF in Warmerly Warmerly rechecks your domain's DNS automatically. DNS changes can take anywhere from a few minutes up to 24 to 48 hours to spread, so if the SPF warning is still showing right after you save, check again later. You do not need a selector for SPF, because it is one record at a fixed location. ## Still stuck? Back to the main guide: [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). The same click-path in GoDaddy is used for [DKIM](https://docs.warmerly.com/guides/dkim/godaddy). To see what is live right now, use the free [SPF checker](https://warmerly.com/spf-checker) or [DMARC checker](https://warmerly.com/dmarc-checker). --- # Set Up a DMARC Record on GoDaddy A **DMARC record** is a TXT record at `_dmarc.yourdomain.com` that tells inbox providers what to do with mail that fails SPF or DKIM, and where to send reports. This guide shows exactly where to add it in GoDaddy. For the background, read [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). ## What you'll need - A mailbox address to receive DMARC reports, for example `dmarc@yourdomain.com`. - SPF and DKIM already set up for your sending domain. See [SPF on GoDaddy](https://docs.warmerly.com/guides/spf/godaddy) and [DKIM on GoDaddy](https://docs.warmerly.com/guides/dkim/godaddy). DMARC checks them, so it is only useful once they pass. ## Step 1: Open your domain's DNS in GoDaddy 1. Go to [godaddy.com](https://www.godaddy.com) and sign in. 2. Open **My Products**, find your domain, and click **DNS** (sometimes shown as **Manage DNS**). 3. You are now on the **DNS Management** page, where the domain's records are listed. ## Step 2: Add the DMARC TXT record 1. Click **Add New Record** (or **Add**) and choose **TXT** as the type. 2. In the **Name** field: Enter `_dmarc` only. GoDaddy adds your domain to the end automatically, so typing `_dmarc.yourdomain.com` would create the wrong record. 3. In the **Value** field: Paste `v=DMARC1; p=none; rua=mailto:you@yourdomain.com`, using your own report address. 4. Leave **TTL** on its default. 5. Click **Save**. | Field | What to enter | | --- | --- | | Type | `TXT` | | Name | `_dmarc` | | Value | `v=DMARC1; p=none; rua=mailto:you@yourdomain.com` | ## Start with p=none, then tighten `p=none` only watches and reports. It is the safe way to start because it cannot block any of your own mail. After a few weeks of clean reports, move to `p=quarantine` (send failures to spam) and later `p=reject` (block them). Jumping straight to `p=reject` risks blocking legitimate mail if an SPF include is missing. ## If you already have a DMARC record A domain can only have **one** DMARC record. If GoDaddy already lists a TXT record at `_dmarc`, edit it instead of adding another. ## Step 3: Check DMARC in Warmerly Warmerly rechecks your domain's DNS automatically. DNS changes can take anywhere from a few minutes up to 24 to 48 hours to spread, so if the DMARC warning is still showing right after you save, check again later. You do not need a selector for DMARC, because it is one record at a fixed location. ## Still stuck? Back to the main guide: [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). The same click-path in GoDaddy is used for [DKIM](https://docs.warmerly.com/guides/dkim/godaddy). To see what is live right now, use the free [SPF checker](https://warmerly.com/spf-checker) or [DMARC checker](https://warmerly.com/dmarc-checker). --- # Set Up an SPF Record on Cloudflare An **SPF record** is a single TXT record that lists which mail servers may send email for your domain. This guide shows exactly where to add it in Cloudflare. If you want the background first, read [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). ## What you'll need - The SPF **include** value from your email provider. For Google Workspace it is `include:_spf.google.com`; for Microsoft 365 it is `include:spf.protection.outlook.com`. Check your provider's help page for the exact value if you use another service. - Access to the domain's DNS in Cloudflare. ## Step 1: Open your domain's DNS in Cloudflare 1. Go to [dash.cloudflare.com](https://dash.cloudflare.com) and sign in. 2. Click the domain you send email from. 3. In the left-hand menu, click **DNS**, then **Records**. ## Step 2: Add the SPF TXT record 1. Click **Add record** and choose **TXT** as the type. 2. In the **Name** field: Enter `@` (this means the root domain, `yourdomain.com`). Some panels leave the field blank for the root instead. Never type the full domain name here. 3. In the **Content** field: Paste your SPF value, for example `v=spf1 include:_spf.google.com ~all`. 4. Leave **TTL** on **Auto**. TXT records are never proxied, so there is no orange-cloud setting to change. 5. Click **Save**. | Field | What to enter | | --- | --- | | Type | `TXT` | | Name | `@` | | Content | `v=spf1 include:_spf.google.com ~all` | ## If you already have an SPF record A domain can only have **one** SPF record. If Cloudflare already shows a TXT record starting with `v=spf1`, **edit that record** and add your new `include:` before the `~all` at the end. Adding a second SPF record breaks SPF for the whole domain, so mail starts failing authentication. For example, to send from Google Workspace and another tool, combine them into one record: ``` v=spf1 include:_spf.google.com include:spf.mailprovider.com ~all ``` SPF also allows at most 10 DNS lookups across all your `include:` entries. If you go over, SPF fails with a "permerror". ## Step 3: Check SPF in Warmerly Warmerly rechecks your domain's DNS automatically. DNS changes can take anywhere from a few minutes up to 24 to 48 hours to spread, so if the SPF warning is still showing right after you save, check again later. You do not need a selector for SPF, because it is one record at a fixed location. ## Still stuck? Back to the main guide: [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). The same click-path in Cloudflare is used for [DKIM](https://docs.warmerly.com/guides/dkim/cloudflare). To see what is live right now, use the free [SPF checker](https://warmerly.com/spf-checker) or [DMARC checker](https://warmerly.com/dmarc-checker). --- # Set Up a DMARC Record on Cloudflare A **DMARC record** is a TXT record at `_dmarc.yourdomain.com` that tells inbox providers what to do with mail that fails SPF or DKIM, and where to send reports. This guide shows exactly where to add it in Cloudflare. For the background, read [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). ## What you'll need - A mailbox address to receive DMARC reports, for example `dmarc@yourdomain.com`. - SPF and DKIM already set up for your sending domain. See [SPF on Cloudflare](https://docs.warmerly.com/guides/spf/cloudflare) and [DKIM on Cloudflare](https://docs.warmerly.com/guides/dkim/cloudflare). DMARC checks them, so it is only useful once they pass. ## Step 1: Open your domain's DNS in Cloudflare 1. Go to [dash.cloudflare.com](https://dash.cloudflare.com) and sign in. 2. Click the domain you send email from. 3. In the left-hand menu, click **DNS**, then **Records**. ## Step 2: Add the DMARC TXT record 1. Click **Add record** and choose **TXT** as the type. 2. In the **Name** field: Enter `_dmarc` only. Cloudflare adds your domain to the end automatically, so typing `_dmarc.yourdomain.com` would create the wrong record. 3. In the **Content** field: Paste `v=DMARC1; p=none; rua=mailto:you@yourdomain.com`, using your own report address. 4. Leave **TTL** on **Auto**. TXT records are never proxied, so there is no orange-cloud setting to change. 5. Click **Save**. | Field | What to enter | | --- | --- | | Type | `TXT` | | Name | `_dmarc` | | Content | `v=DMARC1; p=none; rua=mailto:you@yourdomain.com` | ## Start with p=none, then tighten `p=none` only watches and reports. It is the safe way to start because it cannot block any of your own mail. After a few weeks of clean reports, move to `p=quarantine` (send failures to spam) and later `p=reject` (block them). Jumping straight to `p=reject` risks blocking legitimate mail if an SPF include is missing. ## If you already have a DMARC record A domain can only have **one** DMARC record. If Cloudflare already lists a TXT record at `_dmarc`, edit it instead of adding another. ## Step 3: Check DMARC in Warmerly Warmerly rechecks your domain's DNS automatically. DNS changes can take anywhere from a few minutes up to 24 to 48 hours to spread, so if the DMARC warning is still showing right after you save, check again later. You do not need a selector for DMARC, because it is one record at a fixed location. ## Still stuck? Back to the main guide: [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). The same click-path in Cloudflare is used for [DKIM](https://docs.warmerly.com/guides/dkim/cloudflare). To see what is live right now, use the free [SPF checker](https://warmerly.com/spf-checker) or [DMARC checker](https://warmerly.com/dmarc-checker). --- # Set Up an SPF Record on IONOS An **SPF record** is a single TXT record that lists which mail servers may send email for your domain. This guide shows exactly where to add it in IONOS. If you want the background first, read [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). ## What you'll need - The SPF **include** value from your email provider. For Google Workspace it is `include:_spf.google.com`; for Microsoft 365 it is `include:spf.protection.outlook.com`. Check your provider's help page for the exact value if you use another service. - Access to the domain's DNS in IONOS. ## Step 1: Open your domain's DNS in IONOS 1. Go to [my.ionos.com](https://my.ionos.com) and sign in. 2. Find your domain, click the gear icon next to it, and choose **DNS**. If you don't see a gear, open **Domains & SSL**, click the domain, then its **DNS** tab. 3. You are now on the DNS settings page, where the domain's records are listed. ## Step 2: Add the SPF TXT record 1. Click **Add Record** and choose **TXT** as the type. 2. In the **Host name** field: Enter `@` (this means the root domain, `yourdomain.com`). Some panels leave the field blank for the root instead. Never type the full domain name here. 3. In the **Value** field: Paste your SPF value, for example `v=spf1 include:_spf.google.com ~all`. 4. Leave **TTL** on its default. 5. Click **Save**. | Field | What to enter | | --- | --- | | Type | `TXT` | | Host name | `@` | | Value | `v=spf1 include:_spf.google.com ~all` | ## If you already have an SPF record A domain can only have **one** SPF record. If IONOS already shows a TXT record starting with `v=spf1`, **edit that record** and add your new `include:` before the `~all` at the end. Adding a second SPF record breaks SPF for the whole domain, so mail starts failing authentication. For example, to send from Google Workspace and another tool, combine them into one record: ``` v=spf1 include:_spf.google.com include:spf.mailprovider.com ~all ``` SPF also allows at most 10 DNS lookups across all your `include:` entries. If you go over, SPF fails with a "permerror". ## Step 3: Check SPF in Warmerly Warmerly rechecks your domain's DNS automatically. DNS changes can take anywhere from a few minutes up to 24 to 48 hours to spread, so if the SPF warning is still showing right after you save, check again later. You do not need a selector for SPF, because it is one record at a fixed location. ## Still stuck? Back to the main guide: [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). The same click-path in IONOS is used for [DKIM](https://docs.warmerly.com/guides/dkim/ionos). To see what is live right now, use the free [SPF checker](https://warmerly.com/spf-checker) or [DMARC checker](https://warmerly.com/dmarc-checker). --- # Set Up a DMARC Record on IONOS A **DMARC record** is a TXT record at `_dmarc.yourdomain.com` that tells inbox providers what to do with mail that fails SPF or DKIM, and where to send reports. This guide shows exactly where to add it in IONOS. For the background, read [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). ## What you'll need - A mailbox address to receive DMARC reports, for example `dmarc@yourdomain.com`. - SPF and DKIM already set up for your sending domain. See [SPF on IONOS](https://docs.warmerly.com/guides/spf/ionos) and [DKIM on IONOS](https://docs.warmerly.com/guides/dkim/ionos). DMARC checks them, so it is only useful once they pass. ## Step 1: Open your domain's DNS in IONOS 1. Go to [my.ionos.com](https://my.ionos.com) and sign in. 2. Find your domain, click the gear icon next to it, and choose **DNS**. If you don't see a gear, open **Domains & SSL**, click the domain, then its **DNS** tab. 3. You are now on the DNS settings page, where the domain's records are listed. ## Step 2: Add the DMARC TXT record 1. Click **Add Record** and choose **TXT** as the type. 2. In the **Host name** field: Enter `_dmarc` only. IONOS adds your domain to the end automatically, so typing `_dmarc.yourdomain.com` would create the wrong record. 3. In the **Value** field: Paste `v=DMARC1; p=none; rua=mailto:you@yourdomain.com`, using your own report address. 4. Leave **TTL** on its default. 5. Click **Save**. | Field | What to enter | | --- | --- | | Type | `TXT` | | Host name | `_dmarc` | | Value | `v=DMARC1; p=none; rua=mailto:you@yourdomain.com` | ## Start with p=none, then tighten `p=none` only watches and reports. It is the safe way to start because it cannot block any of your own mail. After a few weeks of clean reports, move to `p=quarantine` (send failures to spam) and later `p=reject` (block them). Jumping straight to `p=reject` risks blocking legitimate mail if an SPF include is missing. ## If you already have a DMARC record A domain can only have **one** DMARC record. If IONOS already lists a TXT record at `_dmarc`, edit it instead of adding another. ## Step 3: Check DMARC in Warmerly Warmerly rechecks your domain's DNS automatically. DNS changes can take anywhere from a few minutes up to 24 to 48 hours to spread, so if the DMARC warning is still showing right after you save, check again later. You do not need a selector for DMARC, because it is one record at a fixed location. ## Still stuck? Back to the main guide: [What Are SPF & DMARC?](https://docs.warmerly.com/guides/spf-dmarc). The same click-path in IONOS is used for [DKIM](https://docs.warmerly.com/guides/dkim/ionos). To see what is live right now, use the free [SPF checker](https://warmerly.com/spf-checker) or [DMARC checker](https://warmerly.com/dmarc-checker). --- # Custom Tracking Domain (And How to Set It Up) This guide explains what a custom tracking domain is, why it matters, and how to set one up for a mailbox in Warmerly. No technical background needed. ## What is tracking, and why does it matter? When you send a campaign email through Warmerly, we can tell you when someone opens that email or clicks a link inside it. This is called **open and click tracking**. Here's how it works behind the scenes: any link you put in your email actually points to a special Warmerly web address first. When someone clicks it, Warmerly notes "this person clicked," and then sends them straight on to the real page. The same trick is used for tracking opens. Without a working custom tracking domain, a mailbox sends with **no tracking and no unsubscribe link at all**: Warmerly puts none of its own addresses in your emails, and you are responsible for including your own way to opt out. A link that shows **your own website's address** looks like it came from a real, established business, because it did. This setting puts your own domain on the tracking and unsubscribe links, which switches both back on. ## What you'll be setting up: a CNAME record To make this work, you need to add one small entry to your domain's **DNS** settings. DNS (Domain Name System) is basically your domain's address book. It's the place where your domain name gets pointed to your website, your email provider, and other services. Your DNS is managed wherever you bought or host your domain, for example, Namecheap, GoDaddy, IONOS, or Cloudflare. The entry you'll add is called a **CNAME record**. In plain English, a CNAME record is a DNS record that points one web address to another. You'll use it to point a subdomain of your own website, something like `track.yourdomain.com`, over to the address Warmerly gives you. Once that's done, tracking links in your emails will show `track.yourdomain.com` and your unsubscribe link lives on that same domain, even though Warmerly is still doing all the tracking behind the scenes. ## Step 1: Get your CNAME details from Warmerly 1. In Warmerly, go to **Accounts**. 2. Click into the mailbox you want to set this up for. 3. Go to **Settings**. 4. Find the **Custom tracking domain** section. There you'll see a box with three pieces of information: | Field | What it means | | --- | --- | | Record | Always `CNAME`, this tells your DNS host what kind of entry to add. | | Host | The subdomain name to use, such as `track`. | | Value | The Warmerly address to point to, exactly as shown in the box. | There's also a text box where you can type the exact subdomain you want to use, for example `track.yourdomain.com`. Type in the domain or subdomain you plan to use, then copy the **Host** and **Value** shown. ## Step 2: Go to your domain's DNS settings This is the same DNS panel you'd use to set up **DKIM** (an email security stamp) or **SPF and DMARC** (two more email security records). If you've already done either of those for this domain, you already know where to go. 1. Log in to your domain host's dashboard. This is the company you bought your domain from (for example, Namecheap, GoDaddy, IONOS, or Cloudflare). 2. Find the **DNS** or **DNS Records** section. If you're not sure how to find this for your specific provider, our other guides walk through it step by step: - [Setting up DKIM](https://docs.warmerly.com/guides/dkim): covers finding the DNS section on Namecheap, GoDaddy, IONOS, and Cloudflare. - [SPF & DMARC records](https://docs.warmerly.com/guides/spf-dmarc): covers the same DNS panel for two more email security records. ## Step 3: Add the CNAME record 1. In your DNS section, choose to add a new record. 2. Set the record type to **CNAME**. 3. In the **host** (sometimes called "name" or "subdomain") field, enter exactly what Warmerly showed you, for example `track`. 4. In the **value** (sometimes called "target" or "points to") field, enter exactly what Warmerly showed you. 5. Save the record. **Copy the host and value exactly as Warmerly shows them.** A typo here is the most common reason this doesn't work, even a missing letter or an extra dot will stop it from verifying. ## Step 4: Wait for Warmerly to confirm it Back in Warmerly, the **Custom tracking domain** section shows two status lights. | Status | What it means | | --- | --- | | **Domain link pending** | Warmerly hasn't found your new CNAME record in DNS yet. This is normal right after you add it. | | **Domain link verified** | Warmerly has found and confirmed your CNAME record. Your tracking links can now use your own domain. | DNS changes don't happen instantly across the internet, they spread out slowly, a bit like ripples in a pond. This can take anywhere from a few minutes up to **24-48 hours**. Don't worry if it still says "pending" right after you add the record, just check back later. ## Step 5: Make sure HTTPS works for your domain You'll also see a second status, for something called **SSL**. SSL stands for the technology behind **HTTPS**, the padlock icon and "secure" label browsers show for trusted websites. Once your CNAME record verifies, Warmerly checks that HTTPS works for your tracking domain with a valid certificate, so links open safely and don't trigger browser warnings. **Warmerly does not issue that certificate for you.** Your domain needs to sit behind a service that holds one for it, for example Cloudflare with the orange-cloud proxy turned on for the CNAME record. | Status | What it means | | --- | --- | | **Secure connection pending** | HTTPS does not work for your domain yet (no valid certificate, or the check has not run since you fixed it). The check repeats every few minutes. | | **Secure connection verified** | HTTPS works. Your tracking and unsubscribe links will open over a secure connection. | **Until both statuses say "verified", your mailbox does not use the domain.** It sends with no tracking and no unsubscribe link, and you are responsible for including your own way to opt out. Once both say "verified," your custom tracking domain is fully live. ## Still stuck? No worries: DNS settings can be fiddly, especially if this is your first time editing them. If you get stuck on any step, click the chat help button in the bottom corner of the Warmerly app. It connects you straight to a real person on our support team who can look at your account and help you sort it out. --- # Connecting a Mailbox This guide walks you through connecting your email inbox (your "mailbox") to Warmerly. Once connected, Warmerly can send warm-up emails and outreach on your behalf, and check your inbox for replies. There are three ways to connect a mailbox: 1. **One-click sign-in**: for Outlook.com, Hotmail and Microsoft 365. No settings to type in. Just sign in. 2. **Gmail app password**: for Gmail and Google Workspace. The server settings fill in by themselves; you paste one generated password. 3. **Manual setup**: for everything else, like Zoho Mail, Namecheap Private Email, or any other email provider. ## One-click sign-in (Outlook, Microsoft 365) If your mailbox is an Outlook.com or Hotmail address, or a Microsoft 365 work address, you can connect it in a few clicks. You don't need to find any settings, passwords, or codes. 1. Go to **Accounts** in your Warmerly dashboard and click **Add**. 2. Choose **Microsoft 365** (work or school) or **Outlook.com or Hotmail** (personal). 3. A sign-in window will pop up. Log in with the email address you want to connect. 4. Approve the permissions Warmerly asks for. This is normal. It's how Warmerly is allowed to send and read email for you. 5. That's it. Your mailbox is connected. This method is called **OAuth**. In plain terms, it just means you're signing in directly with Microsoft, and they hand Warmerly a secure permission slip instead of your password. Warmerly never sees or stores your actual password. **If you don't see your mailbox as connected after signing in,** try again and make sure you clicked "Allow" or "Accept" on every permission screen. If it still doesn't work, you can always fall back to manual setup below using an app password (explained further down). ## Gmail and Google Workspace (app password) Gmail and Google Workspace connect with a Google **app password**: a separate password Google generates just for this connection. It is not your normal Google password, and you can revoke it from your Google account at any time without changing anything else. 1. Turn on **2-Step Verification** on your Google account if it isn't on already. Google only offers app passwords once it is. 2. Go to [myaccount.google.com/apppasswords](https://myaccount.google.com/apppasswords), give the password a name (for example "Warmerly"), and copy the 16-character password Google shows you. 3. In Warmerly, go to **Accounts → Add** and choose **Gmail or Google Workspace**. 4. Enter your email address and paste the app password. The server settings are filled in for you. 5. Click **Test connection**, then save. ### Google Workspace: "The setting you are looking for is not available for your account" On a Google Workspace user (a mailbox on your company's own domain), the app passwords page often says *"The setting you are looking for is not available for your account"* or *"Your account doesn't support the setting you're trying"*. Almost always, that account does not have **2-Step Verification** on yet — and on Workspace, the admin has to allow it first. If you manage the Workspace yourself, you can fix it in a few minutes: 1. Sign in to [admin.google.com](https://admin.google.com) with an **admin** account. 2. Go to **Security → Authentication → 2-Step Verification**. 3. Tick **Allow users to turn on 2-Step Verification**. Under **Methods**, choose **Any** , not "Only security key", which also blocks app passwords. Save. It usually applies within minutes, but Google says it can take up to 24 hours. 4. Sign in as the mailbox user, open [myaccount.google.com/security](https://myaccount.google.com/security) and turn on **2-Step Verification** (a phone or Google Authenticator is fine). 5. Open [myaccount.google.com/apppasswords](https://myaccount.google.com/apppasswords) again, you can now create the app password. Still not available after that? The account may be enrolled in Google's **Advanced Protection Program** (which disables app passwords), or it may be in an organizational unit where 2-Step Verification is restricted, check the setting on that user's org unit in the Admin console. If you don't run the Workspace, forward these steps to your admin. Every mailbox user needs its own app password: Google has no bulk option for them, and Warmerly does not currently support Google's domain-wide delegation for connecting a whole Workspace in one step. Warmerly stores the app password encrypted. To cut the connection from Google's side, delete the app password at the same address. ## Manual setup (Zoho Mail, Namecheap Private Email, or any other provider) If your email provider isn't Gmail or Outlook, you'll connect it by typing in your mail server settings yourself. This sounds technical, but it's really just filling in a form with a few values that are almost always the same for a given provider. ### What SMTP and IMAP mean Warmerly needs two pieces of information to work with your mailbox: - **SMTP** is the setting that lets Warmerly *send* email from your address. Think of it as the "outgoing mail" setting. - **IMAP** is the setting that lets Warmerly *read* your inbox, so it can see replies and track your warm-up activity. Think of it as the "incoming mail" setting. Warmerly needs both. Sending without reading means Warmerly couldn't see replies. Reading without sending means Warmerly couldn't actually warm up or send outreach from your address. That's why the manual setup form asks for both an SMTP host/port and an IMAP host/port. A "host" is just the address of your email provider's mail server (something like `smtp.zoho.com`), and a "port" is a number that tells the connection which door to use on that server (like `465` or `993`). You don't need to understand why these numbers are what they are, just copy them in correctly. ### Host and port settings for common providers | Provider | SMTP host (sending) | SMTP port | IMAP host (reading) | IMAP port | | --- | --- | --- | --- | --- | | Zoho Mail | `smtp.zoho.com` | `465` | `imap.zoho.com` | `993` | | Namecheap Private Email | `mail.privateemail.com` | `465` | `mail.privateemail.com` | `993` | If your provider isn't listed here, don't worry. Almost every email provider publishes these settings on their support site. Search **"[your provider name] SMTP IMAP settings"** (for example, "Bluehost SMTP IMAP settings") and you'll usually find the exact host and port to use within the first result or two. ### "My IMAP login is different from SMTP" checkbox On the manual setup form, you'll see a checkbox labeled **"My IMAP login is different from SMTP."** For most people, you can leave this unchecked, because most providers let you use the same email address and password for both sending and reading mail. Some providers (especially business or enterprise email systems) issue a separate username or a separate app-specific password just for reading mail (IMAP), different from the one used for sending (SMTP). If your provider does this, check the box. A second set of login fields will appear so you can enter the IMAP-specific username and password separately. If you're not sure whether your provider does this, try leaving the box unchecked first. The **Test connection** button (see below) will tell you right away if the IMAP login needs to be separate. ### App passwords for Outlook (if setting up manually) Most people should use one-click sign-in for Outlook and Microsoft 365. If you have a reason to set one up manually instead, Microsoft usually blocks your normal account password from being used this way, and you'll need a special **app password**: a generated password just for this connection. (Gmail always works this way, see the Gmail section above.) - **Outlook / Microsoft 365:** Go to [account.microsoft.com/security](https://account.microsoft.com/security) and look for the option to create an app password. Use that generated password in the Warmerly form instead of your normal Microsoft password. Keep this app password somewhere safe. You can always come back and generate a new one if you lose it. ### Test your connection before saving Before you save your mailbox settings, click the **Test connection** button on the setup form. Warmerly will try both the SMTP (sending) and IMAP (reading) settings right away. - If both succeed, you'll see a confirmation and you're ready to save. - If one fails, Warmerly will tell you exactly which one (SMTP or IMAP) so you know which host, port, or password to double-check, instead of guessing. **Always run Test connection before saving.** It only takes a few seconds, and it saves you from finding out something's wrong later when your emails silently fail to send or Warmerly can't see your replies. ## Microsoft 365: "authentication unsuccessful" after a successful reconnect If Microsoft says the connection succeeded but Warmerly still reports a sending authentication error (SMTP `535 5.7.3`), it is almost never a password problem, a mailbox connected with one-click has no password. There are three usual causes. ### 1. The sign-in address isn't the mailbox address Warmerly sends over SMTP and IMAP (not Microsoft Graph), and Microsoft checks the username against the **mailbox's primary SMTP address**. That address is allowed to differ from the address you sign in to Microsoft with, for example signing in as `jwilson@contoso.onmicrosoft.com` for a mailbox that receives as `jake.wilson@contoso.com`. If the two differ, Microsoft rejects the login. Reconnecting the mailbox reads the correct address straight from Microsoft and updates it. If you'd rather set it yourself, open the mailbox → **Settings → Mailbox login (advanced)** and put the mailbox's primary SMTP address in the SMTP and IMAP username fields. ### 2. Authenticated SMTP is switched off Microsoft reports this as `535 5.7.139 ... SmtpClientAuthentication is disabled for the Tenant`. It is not a credential problem. SMTP AUTH is off by default on tenants created since 2020, and it blocks sending for every app, not just Warmerly. Receiving replies over IMAP is governed separately and usually keeps working. An admin can An admin can re-enable it for the mailbox in the Microsoft 365 admin centre → **Users → Active users →** select the user **→ Mail → Manage email apps → Authenticated SMTP**. If the organisation has disabled it tenant-wide, it also has to be turned on for the tenant (see Microsoft's guide at aka.ms/smtp_auth_disabled). A Conditional Access policy or security defaults blocking legacy authentication will do the same thing. ### 3. Sending from an alias or a shared mailbox Supported: set the SMTP/IMAP username under **Settings → Mailbox login (advanced)** to that address. The account you connected needs **Send As** permission (for sending) or **Full Access** (for reading replies) on the mailbox in Exchange; without it Microsoft returns the same error. ### Getting the exact error Open the mailbox and click **Test connection**. Warmerly shows the plain-language reason and the raw response from the mail server, including the exact SMTP code, which is what support needs if none of the above fixes it. --- # Deliverability checklist before you launch Work through this before your first campaign, and again when you add a new domain. It is ordered by how much each step matters. Nothing here needs technical skill, and each item links to the page that walks you through it. ## 1. Set up the domain - [ ] **MX records exist.** A domain that cannot receive replies looks disposable, and warmup needs replies. See [DNS records](https://docs.warmerly.com/guides/dns-records). - [ ] **SPF: one record**, ending safely, under 10 DNS lookups. See [SPF & DMARC](https://docs.warmerly.com/guides/spf-dmarc). - [ ] **DKIM is published** and Warmerly can see it. If it says "none" but your provider signs your mail, set the **DKIM selector** in the mailbox's **Settings** tab. See [DKIM](https://docs.warmerly.com/guides/dkim). - [ ] **DMARC exists.** `p=none` is a fine start. It will show a warning on the domain health card, and that is normal. - [ ] **The domain health card shows no fail.** Open **Accounts**, click the mailbox, **Health** tab. Warn and information items can wait. See [Domain health card](https://docs.warmerly.com/help/domain-health-card). - [ ] **No blocklist listing** for the domain or mail server. See [Blocklists](https://docs.warmerly.com/help/blocklisted), or check for free at [warmerly.com/blacklist-checker](https://warmerly.com/blacklist-checker). Not sure of your domain's state? The free [deliverability checker](https://warmerly.com/deliverability-checker) reads all four records in seconds. See [Free deliverability tools](https://docs.warmerly.com/help/free-deliverability-tools). ## 2. Use the right kind of domain and mailbox - [ ] **Send cold email from a separate domain**, not your main website domain, so a problem never touches your everyday mail. - [ ] **Keep it to a few mailboxes per domain.** Warmerly warns when a campaign uses more than 5 sending mailboxes on one domain, because they share one reputation. Spread volume across domains. - [ ] **Mailboxes are connected and show no Reconnect button.** See [Connecting a mailbox](https://docs.warmerly.com/guides/mailbox-connection) and [Mailbox won't connect](https://docs.warmerly.com/help/mailbox-wont-connect). ## 3. Warm up before you send hard - [ ] **Warmup is on** for every sending mailbox, and stays on. See [How warmup works](https://docs.warmerly.com/how-warmup-works). - [ ] **You are not raising the daily limit early.** New mailboxes default to 30 campaign emails a day and the ramp holds the first days lower. A mailbox is fully ramped after 30 days, and about two weeks is enough to start gently. - [ ] **You can launch on day one if you keep it small.** When your mailboxes are under 14 days into warmup, a new campaign starts with a gradual volume ramp by default: 3 emails per mailbox on the first day. See [Launch your first campaign](https://docs.warmerly.com/help/launch-first-campaign). - [ ] **Health is not Needs attention.** See [Mailbox health](https://docs.warmerly.com/help/mailbox-health). - [ ] **Optional but useful:** run a [placement test](https://docs.warmerly.com/help/placement-tests) on **Health**. It uses one of your monthly tests. ## 4. Clean the list Most reputation damage comes from bad addresses, not bad copy. - [ ] **Verify addresses before importing.** See [Verify emails](https://docs.warmerly.com/verify). Importing does run a basic check that catches badly formed addresses, disposable domains and domains with no mail server, but it does not confirm that each mailbox exists. - [ ] **Remove addresses you have already emailed** or that asked not to be contacted. Your [suppression list](https://docs.warmerly.com/suppression) is never emailed. - [ ] **Do not use a bought list.** It is the most common cause of a bounce-rate pause. See [Why did sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused). ## 5. Check the message - [ ] **Run subject and body through the** [spam word checker](https://warmerly.com/spam-word-checker). Warmerly's start-campaign check warns at a score of 25 out of 100 or more. - [ ] **Few links and images.** The start-campaign check warns above 5 links or 3 images in one email. Two or three lines of plain text with one link, or none, delivers best. - [ ] **Try plain text.** Plain-text mode sends no HTML part, no tracking pixel and no wrapped links. It also sends no signature. It is the safest format for a first email. - [ ] **Preview a real lead** on the sequence step, so merge tags are filled in and nothing shows a blank or a raw tag. - [ ] **Paste HTML into the** [email HTML checker](https://warmerly.com/email-html-checker) if you use a designed template. ## 6. Decide on tracking - [ ] **Open tracking is off by default.** Leave it off unless you need it, because a tracking pixel that fails to load is itself a warning sign for some inbox clients. - [ ] **If you track clicks or opens, use your own tracking domain.** Without one, links use a shared Warmerly link domain, and other senders' behaviour can affect it. Warmerly warns you at start when tracking is on and a mailbox has no verified tracking domain. See [Custom tracking domain](https://docs.warmerly.com/guides/custom-tracking-domain). ## 7. Set volume and timing - [ ] **Keep the volume ramp on** for new mailboxes (campaign **Settings**, **Advanced**, **Ramp volume up gradually**). - [ ] **Leave the sending window and days at sensible business hours** for your prospects. - [ ] **Keep each mailbox's daily limit modest.** The limit is shared by every campaign that mailbox sends for. ## 8. Start, then watch - [ ] **Start the campaign** and read any readiness warnings. A warning does not block you, but you have to acknowledge it once. - [ ] **Check bounces in the first two days.** If a mailbox's bounce rate reaches 2%, Warmerly starts throttling it, and at 7% it pauses. See [Why did sending slow down or pause?](https://docs.warmerly.com/help/sending-slowed-or-paused). - [ ] **Watch the Health tab and your alerts.** Warmerly emails you about failing DNS records, a new blocklist listing, a disconnect and a falling health score. - [ ] **Reply to and read replies** in **Inbox**. Real conversation helps your reputation. ## What no checklist can promise - Inbox placement is never guaranteed. Providers change their filters and do not publish them. - Warmerly cannot see your spam complaint rate at Gmail or Microsoft. - A mailbox on a brand-new domain takes longer to earn trust than one on an established domain. ## Related - [Domain health card](https://docs.warmerly.com/help/domain-health-card) - [Free deliverability tools](https://docs.warmerly.com/help/free-deliverability-tools) - [How our email infrastructure works](https://docs.warmerly.com/infrastructure) - [Troubleshooting](https://docs.warmerly.com/troubleshooting) --- # Accounts An **account** (also called a mailbox or sender account) is a connected email inbox used for warmup and/or campaign sending, for example a Gmail, Outlook, Zoho, Namecheap, or custom SMTP/IMAP mailbox. Every account belongs to a project and carries its own warmup status, ramp schedule, health score, and sending limits. All endpoints below require `X-Api-Key`. Most also require `X-Project-Id`, see [Authentication](https://docs.warmerly.com/authentication). ## The account object Responses never include raw credentials: SMTP/IMAP passwords and OAuth tokens are encrypted at rest and stripped from the API response entirely. A typical account looks like this: ```json { "id": "3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10", "projectId": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "kind": "real", "email": "sales@yourdomain.com", "displayName": "Alex Carter", "provider": "custom", "authMethod": "password", "smtpHost": "smtp.yourdomain.com", "smtpPort": 587, "smtpUser": "sales@yourdomain.com", "imapHost": "imap.yourdomain.com", "imapPort": 993, "imapUser": "sales@yourdomain.com", "timezone": "UTC", "status": "aging", "createdAt": "2026-06-20T09:12:00.000Z", "activatedAt": null, "dailyCap": 30, "currentRampDay": 0, "rampScheduleId": null, "lastHealthScore": null, "lastSendAt": null, "consecutiveFailures": 0, "needsReconnect": false, "notes": null, "dnsLastCheckedAt": null, "dnsOverallStatus": null, "senderFirstName": null, "senderLastName": null, "replyToAddress": null, "dailyCampaignLimit": 30, "minWaitMinutes": 10, "trackingDomain": null, "warmupFilterTag": null, "warmupDailyLimit": 30 } ``` `status` is one of `aging`, `active`, `paused`, `flagged`, `dead`. Newly connected accounts start as `aging` while warmup ramps up sending volume. ## List accounts ``` GET /accounts ``` Returns the accounts for a single project when `X-Project-Id` is set. If you omit `X-Project-Id`, this endpoint falls back to returning every account across all projects in your **current active workspace**: useful for a workspace-wide overview. ```bash curl https://app.warmerly.com/api/v1/accounts \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" ``` ```json { "accounts": [ { "id": "3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10", "email": "sales@yourdomain.com", "provider": "custom", "status": "aging", "dailyCap": 30 } ] } ``` ## Connect an account ``` POST /accounts ``` Connects a mailbox using manual SMTP/IMAP credentials. Requires a plan that includes the email channel, see the [error](#errors) below if it's not. | Field | Type | Required | Description | | --- | --- | --- | --- | | `email` | string | Yes | The mailbox's email address. | | `displayName` | string | No | Friendly name shown in the dashboard. | | `provider` | string | Yes | One of `gmail`, `outlook`, `zoho`, `namecheap`, `custom`. | | `smtp.host` | string | Yes | SMTP server hostname. | | `smtp.port` | integer | Yes | SMTP server port. | | `smtp.user` | string | Yes | SMTP username. | | `smtp.pass` | string | Yes | SMTP password or app password. Encrypted at rest, never returned. | | `imap.host` | string | Yes | IMAP server hostname. | | `imap.port` | integer | Yes | IMAP server port. | | `imap.user` | string | Yes | IMAP username. | | `imap.pass` | string | Yes | IMAP password or app password. Encrypted at rest, never returned. | | `timezone` | string | No | IANA timezone for scheduling sends. Defaults to `UTC`. | | `rampScheduleId` | string (UUID) | No | Ramp schedule to control warmup volume growth. | ```bash curl -X POST https://app.warmerly.com/api/v1/accounts \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" \ -H "Content-Type: application/json" \ -d '{ "email": "sales@yourdomain.com", "displayName": "Alex Carter", "provider": "custom", "smtp": { "host": "smtp.yourdomain.com", "port": 587, "user": "sales@yourdomain.com", "pass": "app-password" }, "imap": { "host": "imap.yourdomain.com", "port": 993, "user": "sales@yourdomain.com", "pass": "app-password" }, "timezone": "Europe/London" }' ``` Returns `201` with the created account: ```json { "account": { "id": "3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10", "projectId": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "kind": "real", "email": "sales@yourdomain.com", "displayName": "Alex Carter", "provider": "custom", "authMethod": "password", "smtpHost": "smtp.yourdomain.com", "smtpPort": 587, "smtpUser": "sales@yourdomain.com", "imapHost": "imap.yourdomain.com", "imapPort": 993, "imapUser": "sales@yourdomain.com", "timezone": "Europe/London", "status": "aging", "dailyCap": 30, "currentRampDay": 0, "rampScheduleId": null } } ``` On creation, Warmerly kicks off a DNS pre-flight check (SPF/DKIM/DMARC) in the background; check `dnsOverallStatus` on a subsequent `GET` to see the result. ## Get an account ``` GET /accounts/{id} ``` ```bash curl https://app.warmerly.com/api/v1/accounts/3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10 \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "account": { "id": "3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10", "email": "sales@yourdomain.com", "provider": "custom", "status": "aging", "dailyCap": 30, "currentRampDay": 4, "lastHealthScore": 87 } } ``` Returns `404` if the account doesn't exist. ## Update an account ``` PATCH /accounts/{id} ``` Updates settings on an existing account. Only send the fields you want to change. A few of the most commonly used fields: | Field | Type | Description | | --- | --- | --- | | `displayName` | string | Friendly name shown in the dashboard. | | `timezone` | string | IANA timezone for scheduling sends. | | `dailyCap` | integer (1-100) | Max warmup emails sent per day. | | `rampScheduleId` | string (UUID) or `null` | Ramp schedule controlling warmup volume growth. | | `notes` | string | Freeform notes shown in the dashboard. | | `dailyCampaignLimit` | integer (0-1000) | Max campaign emails sent per day from this account. | | `senderFirstName` / `senderLastName` | string or `null` | Overrides the sender identity used in campaign merge fields. | | `replyToAddress` | string or `null` | Reply-to address for outgoing campaign mail. | Beyond these, there are 15+ additional fields for fine-tuning warmup behavior (e.g. `warmupDailyLimit`, `warmupIncreasePerDay`, `warmupReplyRatePct`, `warmupReadEmulation`, `warmupOpenRatePct`) and tracking-domain configuration (`trackingDomain`, `trackingDomainVerified`). These map directly to the warmup/tracking settings available in the dashboard's account settings panel. ```bash curl -X PATCH https://app.warmerly.com/api/v1/accounts/3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10 \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "dailyCap": 45, "notes": "Ramping faster for Q3 push" }' ``` ```json { "account": { "id": "3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10", "dailyCap": 45, "notes": "Ramping faster for Q3 push" } } ``` ## Disconnect an account ``` DELETE /accounts/{id} ``` Permanently disconnects and removes the account, including its warmup history. ```bash curl -X DELETE https://app.warmerly.com/api/v1/accounts/3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10 \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "ok": true } ``` Returns `404` if the account doesn't exist. ## Connect several accounts at once ``` POST /accounts/bulk ``` Requires `X-Project-Id`. Takes `{ "accounts": [...] }`, where each item has `email`, `provider` (`gmail` | `outlook` | `zoho` | `namecheap` | `custom`), `smtp` and `imap` objects, and optional `displayName` and `timezone` (default `UTC`). Capacity is **all-or-nothing**: if the batch would breach the plan's mailbox limit the whole request is refused with `402 plan_capacity` rather than importing the first few. A billing-locked workspace is refused with `402 billing_locked`. Past that gate each account is inserted independently, so one bad row does not lose the others: ```json { "results": [ { "index": 0, "email": "a@yourdomain.com", "ok": true, "id": "3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10" }, { "index": 1, "email": "b@yourdomain.com", "ok": false, "error": "duplicate key value violates unique constraint" } ] } ``` Each connected mailbox starts with `status: "aging"` and warmup already started. ## Check settings before you connect ``` POST /accounts/detect POST /accounts/test-connection ``` `detect` takes `{ "email": "you@yourdomain.com" }` and returns `{ "detection": { … } }`: Warmerly's best guess at the provider, from the domain's live MX records, with the SMTP/IMAP hosts and ports the dashboard's connect wizard would prefill. A domain it cannot place comes back as an `unsupported` kind with a human-readable `note` rather than an error. `test-connection` takes full `smtp` and `imap` objects (`host`, `port`, `user`, `pass`) and reports whether each side authenticated, without saving anything. Use it to surface a credential problem before creating an account that would immediately pause. ```json { "smtp": { "ok": true }, "imap": { "ok": false, "message": "Invalid credentials" } } ``` ## Domain health (records + blocklists in one call) ``` GET /accounts/{id}/domain-health POST /accounts/{id}/domain-health ``` The single call behind the domain-health card in the dashboard, and the one to reach for first: it returns the record checks **and** the blocklist checks for the sending domain and its sending IP together, with per-record advisories rather than a bare pass/fail. ```json { "domain": "yourdomain.com", "providerManaged": false, "dns": { "spfStatus": "pass", "dkimStatus": "none", "dmarcStatus": "pass", "mxStatus": "pass", "findings": [{ "record": "dkim", "severity": "warn", "title": "No DKIM record found" }], "checkedAt": "2026-09-12T08:14:00.000Z" }, "domainBlocklist": { "subject": "yourdomain.com", "status": "clean", "listings": [], "zonesQueried": ["dbl.spamhaus.org"], "zonesErrored": [], "checkedAt": "2026-09-12T08:14:00.000Z" }, "ipBlocklist": { "subject": "203.0.113.10", "via": "smtp.yourprovider.com", "status": "clean", "listings": [], "zonesQueried": [], "zonesErrored": [], "checkedAt": "2026-09-12T08:14:00.000Z" }, "ipSkippedReason": null } ``` | Field | Description | | --- | --- | | `providerManaged` | `true` for gmail.com, outlook.com and the like: the records belong to the provider, so a DKIM reading of them is unreliable and nothing here is your responsibility to fix. | | `dns.findings` | Advisories beyond presence, SPF's `all` qualifier and its 10-lookup budget, DKIM key length and test mode, DMARC policy/`pct`/`rua`. | | `domainBlocklist` / `ipBlocklist` | Listings on public blocklists, with the zones actually queried and any that errored, so a partial answer is visible as partial. | | `ipSkippedReason` | Why there is no IP section (a provider-shared host, an unresolvable SMTP host). A hole with no reason reads as something silently broken. | `POST` re-runs everything and returns the same payload. It is **rate-limited internally**: a re-check inside the minimum interval reuses the stored result rather than re-querying a dozen third-party blocklist zones, so holding down a refresh button cannot multiply Warmerly's query volume across them. The two endpoints below remain, and are the narrower views of the same data. ## DNS and domain checks ``` GET /accounts/{id}/dns POST /accounts/{id}/dns ``` `GET` returns the last 10 DNS checks for the account's domain, newest first, plus `latest` as a convenience. `POST` re-runs the check now and returns `{ "result": { … } }`. ```json { "latest": { "id": "b1e7c2a4-0c3e-4c0a-9a6f-2b7d8e5f1a33", "accountId": "3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10", "domain": "yourdomain.com", "checkedAt": "2026-09-11T08:14:00.000Z", "spfStatus": "pass", "spfRecord": "v=spf1 include:_spf.google.com ~all", "dkimStatus": "none", "dkimSelector": null, "dkimRecord": null, "dmarcStatus": "pass", "dmarcRecord": "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com", "overallStatus": "warn" }, "history": [] } ``` Each record status is `pass`, `none`, `fail` or `error`; `overallStatus` is `pass`, `warn` or `fail`. Two things to know before you treat a result as a verdict: - `error` means DNS did not answer (timeout or resolver problem), **not** that the record is wrong. Re-check rather than re-publishing records. - `dkimStatus: "none"` can mean "present but under a selector Warmerly could not guess", the check tries a list of common selector names and cannot discover an arbitrary one. Set `dkimSelector` on the account (see [Update an account](#update-an-account)) and re-check. Only SPF, DKIM and DMARC are checked here. Everything each record does, and the order to publish them in, is in the [DNS records checklist](https://docs.warmerly.com/guides/dns-records). ## Placement tests ``` GET /accounts/{id}/placement POST /accounts/{id}/placement ``` `GET` lists this account's placement tests with a summary: ```json { "tests": [ { "id": "6d2f0b1a-9c4e-4f77-bb31-2a9e7c4d8e55", "accountId": "3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10", "startedAt": "2026-09-10T09:00:00.000Z", "completedAt": "2026-09-10T09:01:04.000Z", "status": "done", "score": 82, "details": { } } ], "summary": { "latestScore": 82, "latestStatus": "done", "latestStartedAt": "2026-09-10T09:00:00.000Z", "latestDegraded": false, "trendDelta": 6 } } ``` `status` is `pending`, `running`, `done` or `failed`. `trendDelta` is the score change against the previous comparable test, or `null` when there is nothing fair to compare with. `latestDegraded` flags a test that ran against an incomplete seed set. Its score is not comparable with a clean one. **`POST` sends live email and spends quota.** It dispatches probe messages from this mailbox to seed addresses across providers and debits one of the workspace's monthly placement tests. Out of allowance returns `402 payment_required` with the used/limit figures and an `upgradeUrl`. The call waits for the probes to dispatch before responding, so expect it to take tens of seconds. ## Blocklist status ``` GET /accounts/{id}/blocklist POST /accounts/{id}/blocklist ``` Whether the account's sending **domain** appears on public DNS blocklists. `GET` returns the last 10 checks; `POST` runs one now, and returns a recent result with `cached: true` rather than re-querying the zones if one was taken moments ago. ```json { "domain": "yourdomain.com", "applicable": true, "latest": null, "history": [] } ``` `applicable: false` means the domain belongs to a free consumer provider (gmail.com and friends), which is never checked. A shared provider's reputation is not yours to read. ## Activity and warmup history ``` GET /accounts/{id}/stats GET /accounts/{id}/events GET /accounts/{id}/log GET /accounts/{id}/warmup-jobs ``` `stats` is today-and-7-day counters for one mailbox: ```json { "sentToday": 24, "pendingToday": 6, "inboxToday": 22, "spamToday": 2, "openRate": 41.5, "replyRate": 12.3 } ``` `openRate` and `replyRate` here are **warmup-network** rates over 7 days, not campaign performance, the two are different metrics with similar names, explained in [How warmup works](https://docs.warmerly.com/how-warmup-works). Either can be `null` when there is nothing to divide by. `events` returns up to 200 lifecycle events, newest first (`{ id, accountId, type, payload, createdAt }`), for example `type: "aged_in"` with `payload: { "rampDay": 45 }`. `log` pages through the individual warmup messages this mailbox sent, newest first: `?limit=` (1-100, default 50) and `?cursor=` (pass the previous response's `nextCursor`). ## Pause, resume and warmup ``` POST /accounts/{id}/pause POST /accounts/{id}/resume POST /accounts/{id}/warmup/toggle POST /accounts/{id}/send-test POST /accounts/{id}/oauth/reconnect ``` `warmup/toggle` takes `{ "enabled": true | false }` and is the supported way to start or stop warmup for one mailbox; enabling it for the first time also stamps the warmup start date the ramp is measured from. The free mailbox every new account is given (`managedBy: "warmerly_sandbox"`) keeps warming for as long as you have it: `pause`, and `warmup/toggle` with `{ "enabled": false }`, answer `409` with code `sandbox_warmup_locked` for it. Delete it (`DELETE /accounts/{id}`) if you no longer want it. `send-test` takes `{ "to": "you@example.com" }` and sends one real message through this mailbox, the fastest way to prove SMTP works end to end. `oauth/reconnect` re-reads a Google/Microsoft mailbox's identity and refreshes its tokens. It is the fix for a Microsoft 365 mailbox that authenticates but fails to send, because a reconnect re-reads the real primary SMTP address, see [Troubleshooting](https://docs.warmerly.com/troubleshooting). ## Channel account limits ``` GET /accounts/limits ``` Workspace-level, no `X-Project-Id`. Reports connected-vs-included counts for the per-account channels (LinkedIn and WhatsApp) with their overage price in USD, plus the OneMail hosted-mailbox add-on: its current quantity, per-mailbox price in minor units, the tier discount, and the full price ladder. ```json { "limits": { "linkedin": { "used": 1, "included": 0, "overageUsd": 50 }, "whatsapp": { "used": 0, "included": 2, "overageUsd": 6 }, "onemail": { "used": 4, "included": null, "unitAmountMinor": 199, "currency": "usd", "billableQuantity": 4, "recurringAmountMinor": 796, "tier": "growth", "discountPercent": 33 } } } ``` `included: null` on `onemail` is not a missing value: hosted mailboxes have no cap at all, they are billed per unit and never consume a plan mailbox slot, so never render that one as a progress bar. For monthly allowances and plan capacity see [Usage & limits](https://docs.warmerly.com/usage). ## OAuth-connected accounts Outlook.com and Microsoft 365 accounts can also be connected via OAuth instead of raw SMTP/IMAP credentials, but that flow is only available through the dashboard's **Add mailbox → Microsoft** wizard, there is no public API endpoint to initiate an OAuth connection. Gmail and Google Workspace connect with SMTP/IMAP and a Google app password (`smtp.gmail.com:465`, `imap.gmail.com:993`); mailboxes connected with Google OAuth before 2026-09-15 keep working. Once connected (by either method), the resulting account is fully manageable through this API. ## Errors Attempting to connect an account on a plan without the email channel returns `403`: ```json { "error": { "code": "channel_not_included", "message": "Your plan does not include email features. Upgrade at /pricing.", "details": { "upgradeUrl": "/pricing" } } } ``` An invalid request body (e.g. malformed `smtp`/`imap` object) returns `400`: ```json { "error": { "code": "bad_request", "message": "invalid_body", "details": { /* zod field errors */ } } } ``` A missing account on `GET`, `PATCH`, or `DELETE` returns `404`: ```json { "error": { "code": "not_found", "message": "not_found", "details": null } } ``` --- # Campaigns A campaign is a multi-step outbound sequence (email, LinkedIn, or a mix) sent to a list of leads on a schedule. WhatsApp steps can be added to a sequence, but WhatsApp sending is not available for campaigns yet: the launch checklist blocks a campaign that contains one until you remove it (see [WhatsApp](https://docs.warmerly.com/help/whatsapp-outreach)). This page covers creating and managing campaigns, their steps, sending accounts, and leads. Campaign-list endpoints (`GET`/`POST /campaigns`) are project-scoped and require `X-Project-Id`. Everything under `/campaigns/{id}/...` is campaign-scoped, the campaign's project is resolved from `{id}` itself, so `X-Project-Id` is **not** required on those routes (access is still checked: your API key's user must belong to the campaign's workspace). ## The campaign object ```json { "id": "b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f", "projectId": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "name": "Q3 outbound - agencies", "status": "draft", "assignedToUserId": null, "targetReplies": null, "targetLeads": null, "dailyLimit": 30, "stopOnReply": true, "stopOnAutoReply": true, "trackOpens": true, "trackClicks": true, "sendingDays": [1, 2, 3, 4, 5], "sendingHourStart": 9, "sendingHourEnd": 17, "timezone": "UTC", "minWaitMinutes": 10, "createdAt": "2026-06-01T09:00:00.000Z", "updatedAt": "2026-06-01T09:00:00.000Z", "startedAt": null, "completedAt": null } ``` `status` is one of `draft`, `active`, `paused`, `completed`, `archived`. ## List campaigns ``` GET /campaigns ``` Requires `X-Project-Id`. Returns every campaign in the project with live counters joined in (lead/email totals), most recently created first. ```bash curl https://app.warmerly.com/api/v1/campaigns \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" ``` ```json { "campaigns": [ { "id": "b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f", "name": "Q3 outbound - agencies", "status": "active", "createdAt": "2026-06-01T09:00:00.000Z", "startedAt": "2026-06-02T09:00:00.000Z", "completedAt": null, "assignedToUserId": null, "assignedToName": null, "assignedToEmail": null, "targetReplies": null, "targetLeads": null, "totalLeads": 240, "completedLeads": 51, "sentCount": 312, "clickCount": 18, "repliedCount": 9, "opportunityCount": 9 } ] } ``` ## Create a campaign ``` POST /campaigns ``` Requires `X-Project-Id`. Creates a campaign in `draft` status with one empty email step seeded automatically (edit or replace it via [Steps](#steps)). | Field | Type | Required | Notes | | --- | --- | --- | --- | | `name` | string (1-200 chars) | yes | | | `timezone` | string | no | IANA timezone string, default `"UTC"` | | `dailyLimit` | integer (1-1000) | no | Default `30` | | `assignedToUserId` | UUID or `null` | no | Must be a member of the campaign's workspace | | `targetReplies` | integer or `null` | no | Optional goal shown against live stats | | `targetLeads` | integer or `null` | no | Optional goal shown against live stats | ```bash curl -X POST https://app.warmerly.com/api/v1/campaigns \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" \ -H "Content-Type: application/json" \ -d '{ "name": "Q3 outbound - agencies", "dailyLimit": 50 }' ``` ```json { "campaign": { "id": "b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f", "name": "Q3 outbound - agencies", "status": "draft", "...": "..." } } ``` Returns `201`. Creating a campaign requires your plan to include the email channel; otherwise returns `403 channel_not_included`. ## Get a campaign ``` GET /campaigns/{id} ``` ```bash curl https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "campaign": { "id": "b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f", "name": "Q3 outbound - agencies", "status": "draft", "...": "..." } } ``` ## Update a campaign ``` PATCH /campaigns/{id} ``` All fields optional: send only what you want to change. | Field | Type | | --- | --- | | `name` | string (1-200 chars) | | `status` | `"draft" \| "active" \| "paused" \| "completed" \| "archived"` | | `dailyLimit` | integer (1-1000) | | `stopOnReply` | boolean | | `stopOnAutoReply` | boolean | | `trackOpens` | boolean | | `trackClicks` | boolean | | `sendingDays` | integer[] (0-6, 0 = Sunday) | | `sendingHourStart` | integer (0-23) | | `sendingHourEnd` | integer (0-23) | | `timezone` | string | | `minWaitMinutes` | integer (0-1440) | | `assignedToUserId` | UUID or `null` | | `targetReplies` | integer or `null` | | `targetLeads` | integer or `null` | `status: "paused"` and `status: "active"` behave exactly like [pause](#pause-a-campaign) and [resume](#resume-a-campaign): only an active campaign can be paused and only a paused one resumed (otherwise `409 conflict`), and they must be sent without other fields. To launch a draft, completed or archived campaign, use `POST /campaigns/{id}/start`. ```bash curl -X PATCH https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "dailyLimit": 75, "sendingHourStart": 8, "sendingHourEnd": 18 }' ``` ```json { "campaign": { "id": "b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f", "dailyLimit": 75, "sendingHourStart": 8, "sendingHourEnd": 18, "...": "..." } } ``` To change `status` directly, use `PATCH` with `{ "status": "..." }`, or prefer the dedicated [`start`](#start-a-campaign), [`pause`](#pause-a-campaign), and [`resume`](#resume-a-campaign) actions below, which also validate that the campaign is actually ready to send. ## Delete a campaign ``` DELETE /campaigns/{id} ``` Deletes the campaign and cascades to its steps, senders, leads, and send history. This cannot be undone. ```bash curl -X DELETE https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "ok": true } ``` ## Start a campaign ``` POST /campaigns/{id}/start ``` Validates the campaign is ready, then flips it to `active` and sets `startedAt` (on first start only, later restarts don't reset it). Checks performed: - At least one step exists that is a valid email step (`subject` + `bodyText`), a LinkedIn step (`linkedin_connection` / `linkedin_message`). A WhatsApp step counts as a step, but WhatsApp sending is not available for campaigns yet, so its sender check fails. - Your plan includes the channel(s) the campaign actually uses. - Your monthly campaign send limit hasn't been reached. - At least one sending account is attached for each channel the campaign uses (email → [senders](#senders-email), LinkedIn → [linkedin-senders](#linkedin-senders)). - At least one lead is `queued`. ```bash curl -X POST https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/start \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "campaign": { "id": "b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f", "status": "active", "startedAt": "2026-07-02T10:00:00.000Z", "...": "..." } } ``` Failing a readiness check returns `400 bad_request` with a human-readable `message` (e.g. `"Add at least one sending mailbox"`). Missing plan access returns `403 channel_not_included`; hitting the monthly send cap returns `402 payment_required`. ## Pause a campaign ``` POST /campaigns/{id}/pause ``` Sets an **active** campaign's `status` to `paused` (pausing one that is already paused is a no-op; any other status returns `409 conflict`). Queued sends stop going out until resumed. ```bash curl -X POST https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/pause \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "campaign": { "id": "b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f", "status": "paused", "...": "..." } } ``` ## Resume a campaign ``` POST /campaigns/{id}/resume ``` Sets a **paused** campaign back to `active`; any other status returns `409 conflict` (use `start` instead). Re-checks your monthly campaign send limit (returns `402 payment_required` if exhausted) but does not re-run the full `start` readiness checks. ```bash curl -X POST https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/resume \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "campaign": { "id": "b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f", "status": "active", "...": "..." } } ``` ## Stats ``` GET /campaigns/{id}/stats ``` Aggregated counters and rates for the campaign. ```bash curl https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/stats \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "leads": { "total": 240, "queued": 168, "active": 21, "completed": 51, "replied": 9, "bounced": 3, "unsubscribed": 2 }, "emails": { "sent": 312, "delivered": 305, "opened": 140, "clicked": 18, "replied": 9, "bounced": 4, "failed": 1 }, "linkedin": { "connectionsSent": 40, "accepted": 22, "messagesSent": 22, "replied": 5 }, "rates": { "openRate": 0.4487179487179487, "clickRate": 0.057692307692307696, "replyRate": 0.028846153846153848, "bounceRate": 0.01282051282051282 } } ``` `rates` are computed from `emails.sent` (0 if nothing has sent yet). ## Steps Steps are the ordered sequence of touches (email, LinkedIn) leads move through, with a delay before each one. ### List steps ``` GET /campaigns/{id}/steps ``` `steps` is the sequence in send order. This is the field to read. The response also carries `nodes`, `edges` and `entryStepId`, the same steps as a graph, which the dashboard's visual editor uses; you can ignore them. A step's `waitDays` / `waitHours` is the delay **before** that step sends, counted from the previous step (the first step's delay is counted from when the lead enters the campaign). ```json { "steps": [ { "id": "c1b2a3d4-1111-4b7a-8e2a-1a2b3c4d5e6f", "campaignId": "b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f", "stepOrder": 1, "kind": "email", "subject": "Quick question about {{companyName}}", "bodyText": "Hi {{firstName}}, ...", "bodyHtml": null, "waitDays": 0, "waitHours": 0, "variants": [], "createdAt": "2026-06-01T09:00:00.000Z" }, { "id": "c1b2a3d4-3333-4b7a-8e2a-1a2b3c4d5e6f", "campaignId": "b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f", "stepOrder": 2, "kind": "email", "subject": "Following up", "bodyText": "Hi {{firstName}}, just bumping this...", "bodyHtml": null, "waitDays": 3, "waitHours": 0, "variants": [], "createdAt": "2026-06-01T09:00:00.000Z" } ], "nodes": ["…the same steps…"], "edges": ["…how they connect…"], "entryStepId": "c1b2a3d4-1111-4b7a-8e2a-1a2b3c4d5e6f" } ``` `kind` is one of `email`, `linkedin_connection`, `linkedin_message`, `whatsapp_message`. `whatsapp_message` is accepted and saved, but a campaign containing one fails the launch checklist (WhatsApp sending is not available for campaigns yet), so remove it before launching. ### Replace steps ``` PUT /campaigns/{id}/steps ``` Replace-all: send the whole sequence, in order, as `steps`. `stepOrder` is assigned from array position, don't send it yourself. | Field | Type | Required | | --- | --- | --- | | `kind` | `"email" \| "wait" \| "linkedin_connection" \| "linkedin_message" \| "whatsapp_message"` | no (default `"email"`) | | `subject` | string or `null` | no (needed for an email step to send) | | `bodyText` | string or `null` | no (needed for an email step to send) | | `bodyHtml` | string or `null` | no | | `waitDays` | integer (0-365) | no (default `0`) | | `waitHours` | integer (0-23) | no (default `0`) | Two ways to space steps out, and you can mix them: - put `waitDays` / `waitHours` on the step itself, or - insert a `{ "kind": "wait", "waitDays": 3 }` entry between two steps. A `wait` entry is not stored as a step of its own. Its delay is added to the next step, so `GET` returns the example below as **two** steps, the second with `waitDays: 3`. A `wait` at the very end is dropped (there is nothing after it to delay). Subjects and bodies support merge tags: `{{firstName}}`, `{{lastName}}`, `{{companyName}}`, `{{email}}`, the sender's `{{senderFirstName}}` / `{{senderName}}`, and any `customVars` key you set on the campaign's leads. **Editing a running campaign:** the Nth email step you send keeps the id of the campaign's existing Nth email step, so rewriting the copy of a live sequence does not move leads off the step they are on. Removing a step that leads are currently waiting at is refused with a `409` (`step_in_use`) and nothing is changed. ```bash curl -X PUT https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/steps -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -H "Content-Type: application/json" -d '{ "steps": [ { "kind": "email", "subject": "Quick question about {{companyName}}", "bodyText": "Hi {{firstName}}, ..." }, { "kind": "wait", "waitDays": 3 }, { "kind": "email", "subject": "Following up", "bodyText": "Hi {{firstName}}, just bumping this..." } ] }' ``` Returns the saved sequence in the same shape as `GET /campaigns/{id}/steps`. | Status | `error.code` | When | | --- | --- | --- | | `400` | `bad_request` | The body is not a valid `steps` array (the details name the field) | | `404` | `not_found` | The campaign doesn't exist or isn't yours | | `409` | `step_in_use` | You removed a step leads are currently waiting at | ## Senders (email) Mailboxes (connected [Accounts](https://docs.warmerly.com/accounts)) that send this campaign's emails, rotated in round-robin to spread volume and protect deliverability. ### List senders ``` GET /campaigns/{id}/senders ``` ```json { "senders": [ { "id": "d1e2f3a4-1111-4b7a-8e2a-1a2b3c4d5e6f", "accountId": "a9b8c7d6-1111-4b7a-8e2a-1a2b3c4d5e6f", "email": "kris@warmerly.com", "provider": "google", "status": "connected", "healthScore": 92, "sentToday": 12, "sentTotal": 340, "lastSentAt": "2026-07-02T09:41:00.000Z" } ] } ``` ### Replace senders ``` PUT /campaigns/{id}/senders ``` Replace-all: pass the full set of `accountId`s that should send this campaign. ```bash curl -X PUT https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/senders \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "accountIds": ["a9b8c7d6-1111-4b7a-8e2a-1a2b3c4d5e6f"] }' ``` ```json { "ok": true } ``` ## LinkedIn senders Connected LinkedIn accounts used for `linkedin_connection` / `linkedin_message` steps. ### List LinkedIn senders ``` GET /campaigns/{id}/linkedin-senders ``` ```json { "senders": [ { "id": "e1f2a3b4-1111-4b7a-8e2a-1a2b3c4d5e6f", "linkedinAccountId": "f1a2b3c4-1111-4b7a-8e2a-1a2b3c4d5e6f", "sentToday": 4, "sentTotal": 61, "lastSentAt": "2026-07-02T09:10:00.000Z", "account": { "id": "f1a2b3c4-1111-4b7a-8e2a-1a2b3c4d5e6f", "...": "..." } } ] } ``` ### Add a LinkedIn sender ``` POST /campaigns/{id}/linkedin-senders ``` `linkedinAccountId` must belong to the authenticated user; adding one that's already attached is a no-op (`sender` is `null` in the response). ```bash curl -X POST https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/linkedin-senders \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "linkedinAccountId": "f1a2b3c4-1111-4b7a-8e2a-1a2b3c4d5e6f" }' ``` ```json { "sender": { "id": "e1f2a3b4-1111-4b7a-8e2a-1a2b3c4d5e6f", "campaignId": "b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f", "linkedinAccountId": "f1a2b3c4-1111-4b7a-8e2a-1a2b3c4d5e6f", "...": "..." } } ``` ### Remove a LinkedIn sender ``` DELETE /campaigns/{id}/linkedin-senders/{sid} ``` `{sid}` is the sender row's `id` (not the LinkedIn account's `id`). ```bash curl -X DELETE https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/linkedin-senders/e1f2a3b4-1111-4b7a-8e2a-1a2b3c4d5e6f \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "deleted": true } ``` ## Leads ### List leads ``` GET /campaigns/{id}/leads ``` | Query param | Default | Max | | --- | --- | --- | | `limit` | `200` | `1000` | | `offset` | `0` |, | ```bash curl "https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/leads?limit=50" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "leads": [ { "id": "11111111-2222-4333-8444-555555555555", "campaignId": "b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f", "leadId": null, "email": "jane@acme.com", "firstName": "Jane", "lastName": "Doe", "companyName": "Acme Inc", "linkedinProfileId": null, "linkedinProfileUrl": null, "linkedinName": null, "linkedinProfilePictureUrl": null, "linkedinHeadline": null, "linkedinCompany": null, "phone": null, "linkedinPostsCache": null, "customVars": { "role": "Head of Growth" }, "status": "queued", "currentStep": 0, "nextRunAt": null, "repliedAt": null, "bouncedAt": null, "unsubscribedAt": null, "createdAt": "2026-06-15T12:00:00.000Z" } ] } ``` `status` is one of `queued`, `active`, `completed`, `replied`, `bounced`, `unsubscribed`, `skipped`. ### Add leads ``` POST /campaigns/{id}/leads ``` Bulk-insert up to 10,000 leads at once. Leads are deduped by lowercased `email` within the request and against existing leads in the campaign (`ON CONFLICT DO NOTHING` on `(campaignId, email)`), duplicates are silently skipped, not errored. | Field | Type | Required | | --- | --- | --- | | `leads[].email` | string (valid email) | yes | | `leads[].firstName` | string or `null` | no | | `leads[].lastName` | string or `null` | no | | `leads[].companyName` | string or `null` | no | | `leads[].customVars` | object of string → string | no | ```bash curl -X POST https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/leads \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "leads": [ { "email": "jane@acme.com", "firstName": "Jane", "lastName": "Doe", "companyName": "Acme Inc", "customVars": { "role": "Head of Growth" } }, { "email": "bob@widgets.io", "firstName": "Bob" } ] }' ``` ```json { "added": 2, "skipped": 0 } ``` ### Remove all leads ``` DELETE /campaigns/{id}/leads ``` Deletes every lead attached to the campaign (no per-lead delete endpoint exists, use this to clear the list, then re-add). ```bash curl -X DELETE https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/leads \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "deleted": 240 } ``` ### Update a lead's email ``` PATCH /campaigns/{id}/leads/{leadId} ``` The only mutable field on an individual lead is `email`, used to fix a bad address found via [Find emails](#find-emails-for-linkedin-leads) or manual correction. ```bash curl -X PATCH https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/leads/11111111-2222-4333-8444-555555555555 \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "email": "jane.doe@acme.com" }' ``` ```json { "lead": { "id": "11111111-2222-4333-8444-555555555555", "email": "jane.doe@acme.com", "...": "..." } } ``` If another lead in the same campaign already has that email, returns `400 bad_request` (`"Another lead in this campaign already has that email"`). ### Import LinkedIn leads ``` POST /campaigns/{id}/leads/import-linkedin ``` Bulk-imports leads from LinkedIn profile data (e.g. a Sales Navigator search or connections list pulled via [Accounts](https://docs.warmerly.com/accounts) LinkedIn integration). Dedupes against existing leads by `linkedinProfileId`. If the campaign already has at least one email [sender](#senders-email) attached, it immediately attempts to find email addresses for the imported leads (best-effort, synchronous). | Field | Type | Required | | --- | --- | --- | | `leads[].id` | string | yes | LinkedIn provider ID (`public_identifier`'s underlying id) | | `leads[].public_identifier` | string | yes | | | `leads[].name` | string | yes | Split into `firstName`/`lastName` | | `leads[].headline` | string or `null` | no | | | `leads[].location` | string or `null` | no | | | `leads[].profile_picture_url` | string or `null` | no | | | `leads[].company_name` | string or `null` | no | Used for the email lookup | | `leads[].profile_url` | string | yes | | Up to 1,000 leads per request. ```bash curl -X POST https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/leads/import-linkedin \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "leads": [ { "id": "ACoAAA1234567", "public_identifier": "jane-doe-1234", "name": "Jane Doe", "headline": "Head of Growth at Acme", "profile_picture_url": "https://media.licdn.com/...", "company_name": "Acme Inc", "profile_url": "https://www.linkedin.com/in/jane-doe-1234" } ] }' ``` ```json { "imported": 1, "skipped": 0, "emailsFound": 1 } ``` ### Find emails for LinkedIn leads ``` POST /campaigns/{id}/leads/find-emails ``` Kicks off email lookups for every lead in the campaign that has a `linkedinProfileUrl` but no `email`, then returns immediately, lookups continue running server-side after the response, subject to your plan's lookup quota. ```bash curl -X POST https://app.warmerly.com/api/v1/campaigns/b6a1e7b0-2f2b-4b7a-8e2a-1a2b3c4d5e6f/leads/find-emails \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "started": 47, "skipped": 0 } ``` `skipped` is nonzero if your remaining lookup quota is smaller than the number of eligible leads, only the leads that fit in the remaining quota are started. If your quota is fully exhausted, returns `400 bad_request` with the quota details in `error.details`. ## Readiness check ``` GET /campaigns/{id}/readiness ``` Everything that would stop this campaign sending, as a list of checks, the same set the dashboard shows before you press start, and worth calling before [`POST /campaigns/{id}/start`](#start-a-campaign) so a failure is explained rather than guessed at. ```json { "ready": false, "checks": [ { "key": "has_steps", "label": "Message sequence has at least one complete step", "ok": true }, { "key": "senders.email", "label": "At least one email sender connected", "ok": true }, { "key": "plan_gates.send_limit", "label": "Monthly campaign send limit not reached", "ok": true }, { "key": "sender_identity", "label": "Sender postal address set for the email footer", "ok": false, "severity": "warning", "detail": "Campaigns send without one, but the footer won't carry it." }, { "key": "leads.queued", "label": "At least one lead queued", "ok": false } ], "usesEmail": true, "usesLinkedin": false, "usesWhatsapp": false } ``` A check with `severity: "warning"` does **not** block sending, `ready` can be `true` with warnings present. Anything without it is a blocker. The `usesX` flags say which channels the sequence actually uses, so a LinkedIn-free campaign is never held up by a LinkedIn check. ## Preview a rendered message ``` POST /campaigns/{id}/preview ``` Renders one step exactly as it would send, merge fields resolved against a real lead, AI opener included, sender identity and footer applied, without sending anything. | Field | Type | Required | Description | | --- | --- | --- | --- | | `stepOrder` | integer (1-based) | One of `stepOrder`/`stepId` | Position of the step in the sequence. Prefer this: `PUT /campaigns/{id}/steps` replaces all steps, so step ids change on every save while positions survive. | | `stepId` | string (UUID) | One of `stepOrder`/`stepId` | A specific step. Exactly one of the two must be given. | | `leadId` | string (UUID) | No | Render against this lead. Defaults to the next lead due out. | | `randomLead` | boolean | No | Render against a random queued lead instead of the next one. | | `regenerate` | boolean | No | Bypass the cached AI opener and generate a fresh one. Spends AI credits. | ```json { "from": { "name": "Jane from Acme", "address": "jane@acme.com" }, "to": "lead@example.com", "lead": { "id": "…", "companyName": "Example Ltd", "firstName": "Sam" }, "subject": "Quick question about Example Ltd", "text": "…", "html": "

…

" } ``` ## Duplicate a campaign ``` POST /campaigns/{id}/duplicate ``` Copies the campaign as a new **draft** named ` (copy)`: every setting (sending window, daily limit, ramp, tracking, stop-on-reply), the full step sequence and its branching edges, and the email/LinkedIn sender assignments. **Leads and send history are not copied.** The copy starts with an empty audience and `startedAt: null`, so duplicating a running campaign cannot re-mail anyone, add leads, then start it. Returns `201` with the new campaign. ## Leads across every campaign ``` GET /campaigns/leads ``` One flat, paged view of every lead in the project's campaigns, rather than one campaign at a time. Project-scoped (`X-Project-Id`). | Query param | Type | Description | | --- | --- | --- | | `campaignId` | string (UUID) | Restrict to one campaign. | | `status` | lead status | Filter by lead status. | | `q` | string | Search name, email or company. | | `limit` / `offset` | integer | Paging. | ```json { "leads": [{ "id": "…", "email": "lead@example.com", "status": "queued", "campaignId": "…", "campaignName": "Q4 outbound" }], "total": 412, "byStatus": { "queued": 380, "replied": 17 }, "campaigns": [{ "id": "…", "name": "Q4 outbound" }] } ``` `campaigns` is the project's own campaigns, so a UI can render the filter without a second call. A project with no campaigns returns empty arrays, not an error. ## Per-lead enrichment and history ``` GET /campaigns/{id}/leads/{leadId}/emails POST /campaigns/{id}/leads/{leadId}/retry-enrichment POST /campaigns/{id}/leads/research ``` `emails` returns every message sent to that lead in this campaign, in order, the audit trail for "what did we actually say to this person". `retry-enrichment` re-runs enrichment (contact-info check, then the paid email-finder fallback) for one lead whose earlier attempt failed or found nothing. Automatic enrichment fires only once per lead, so this is the only way to give a failed lookup another go. It debits the **email lookup** allowance and returns `402 payment_required` when that is exhausted. `research` generates website research summaries, which feed personalisation, for up to **20 leads per call**: pass `{ "leadIds": ["…"], "force": false }`. It is idempotent per lead: leads that already have a fresh summary are skipped unless `force` is `true`. The response reports a per-lead result so a partial failure is visible rather than silent. It spends AI credits ([Usage & limits](https://docs.warmerly.com/usage)). ## Errors Common errors specific to campaign endpoints: | Status | `code` | When | | --- | --- | --- | | `400` | `bad_request` | Invalid body, invalid campaign/lead id, or a `start` readiness check failed | | `403` | `forbidden` | Authenticated user isn't a member of the campaign's workspace | | `402` | `payment_required` | A LinkedIn campaign needs an active standalone LinkedIn slot | | `404` | `not_found` | Campaign, lead, or LinkedIn sender not found | | `402` | `payment_required` | Monthly campaign send limit reached | ```json { "error": { "code": "payment_required", "message": "Purchase a $19/month LinkedIn slot before starting this campaign.", "details": { "upgradeUrl": "/settings/billing" } } } ``` --- # Warmup Warmup endpoints report on the health of your mailboxes and the automated inbox-placement emails Warmerly sends and receives between accounts. Use them to build dashboards, alert on score drops, or list the individual warmup emails sent for an account. ## Get warmup stats ``` GET /warmup/stats ``` Returns a point-in-time summary across your accounts: how many are active, aging, or paused, how many warmup emails have gone out today, and the average health score. `X-Project-Id` is optional here, omit it to get stats across every project in your current workspace, or pass it to scope the numbers to a single project. ```bash curl https://app.warmerly.com/api/v1/warmup/stats \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" ``` ```json { "activeAccounts": 12, "agingAccounts": 3, "pausedAccounts": 1, "todaySent": 84, "todayScheduled": 96, "avgHealthScore": 87 } ``` | Field | Type | Description | | --- | --- | --- | | `activeAccounts` | integer | Accounts with `status = active` (past the ramp period). | | `agingAccounts` | integer | Accounts still ramping up (`status = aging`). | | `pausedAccounts` | integer | Accounts with warmup paused. | | `todaySent` | integer | Warmup emails sent or processed today (UTC). | | `todayScheduled` | integer | Warmup emails still pending for today (UTC). | | `avgHealthScore` | integer \| null | Average `last_health_score` across accounts that have one. | ## Get warmup trends ``` GET /warmup/trends ``` Returns a daily time series plus a current-vs-previous-window summary, suitable for charting score and inbox-placement rate over time. Backed by daily `health_snapshots` rows, aggregated across the accounts you have access to. `X-Project-Id` is optional, same as `/warmup/stats`, pass it to scope to one project. | Query param | Type | Default | Description | | --- | --- | --- | --- | | `days` | `7` \| `30` \| `90` | `30` | Length of the window. Any other value falls back to `30`. | ```bash curl "https://app.warmerly.com/api/v1/warmup/trends?days=30" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" ``` ```json { "range": { "days": 30, "from": "2026-06-03", "to": "2026-07-02" }, "series": [ { "date": "2026-06-03", "sent": 41, "inbox": 37, "spam": 3, "bounce": 1, "score": 82 }, { "date": "2026-06-04", "sent": 45, "inbox": 42, "spam": 2, "bounce": 1, "score": 84 } ], "summary": { "avgScore": 87, "avgScorePrev": 81, "avgScoreDelta": 6, "inboxRate": 92, "inboxRatePrev": 88, "inboxRateDelta": 4, "sentTotal": 1240, "sentTotalPrev": 1105 } } ``` `series` is ordered ascending by `date` and covers the requested window only. `summary` compares the requested window (`cur`) against the equal-length window immediately before it (`prev`); any rate is `null` when there's no data to divide by. `inboxRate` is `inbox / (inbox + spam + bounce)`, expressed as a whole-number percentage. ## List warmup jobs ``` GET /warmup/jobs ``` Returns individual warmup emails (a "job" is one email sent from one warmed mailbox to another), most recent first. This endpoint doesn't take `X-Project-Id`, filter by `account_id` to scope results to a specific mailbox. | Query param | Type | Description | | --- | --- | --- | | `status` | `pending` \| `sending` \| `sent` \| `processed` \| `failed` | Filter by job status. | | `account_id` | uuid | Only jobs where this account is the sender or recipient. | | `limit` | integer, 1-100 | Default `50`. | ```bash curl "https://app.warmerly.com/api/v1/warmup/jobs?account_id=1c2d3e4f-...&status=processed&limit=20" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "jobs": [ { "id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", "senderAccountId": "1c2d3e4f-1111-4a2b-8c3d-4e5f6a7b8c9d", "recipientAccountId": "2d3e4f5a-2222-4a2b-8c3d-4e5f6a7b8c9d", "scheduledAt": "2026-07-02T08:00:00.000Z", "sentAt": "2026-07-02T08:00:42.000Z", "status": "processed", "subject": "Re: quick question about the roadmap", "deliveredFolder": "inbox", "wasOpened": true, "wasReplied": false, "emailType": "reply" } ] } ``` | Field | Type | Description | | --- | --- | --- | | `id` | uuid | Job ID. | | `senderAccountId` / `recipientAccountId` | uuid | The two mailboxes involved in the exchange. | | `scheduledAt` | timestamp | When the job was scheduled to send. | | `sentAt` | timestamp \| null | When it actually sent. | | `status` | string | `pending`, `sending`, `sent`, `processed`, or `failed`. | | `subject` | string | Subject line used. | | `deliveredFolder` | `inbox` \| `spam` \| `promotions` \| `unknown` \| null | Where the recipient mailbox filed it, once processed. | | `wasOpened` / `wasReplied` | boolean | Whether the recipient side opened or replied to it. | | `emailType` | string \| null | Internal template category (e.g. `intro`, `reply`). | ## Per-account health and job history Two account-scoped endpoints give you the same data filtered to a single mailbox. Both take the account ID from the URL, not `X-Project-Id`. ### Get an account's health snapshots ``` GET /accounts/{id}/health ``` | Query param | Type | Default | Description | | --- | --- | --- | --- | | `days` | integer, 1-365 | `90` | How far back to return daily snapshots. | ```bash curl "https://app.warmerly.com/api/v1/accounts/1c2d3e4f-.../health?days=30" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "health": [ { "id": "b3e1c9a0-....", "accountId": "1c2d3e4f-....", "date": "2026-07-02", "sentCount": 22, "inboxCount": 20, "spamCount": 1, "bounceCount": 1, "replyCount": 3, "openCount": 17, "score": 89, "trend": "up", "spamScore": 0, "computedAt": "2026-07-02T00:15:00.000Z" } ] } ``` `health` is ordered most recent first. `trend` is `up`, `flat`, or `down` relative to the previous day's `score`. ### Get an account's warmup job history ``` GET /accounts/{id}/warmup-jobs ``` Returns the last 100 jobs (sent or received) for the account, plus a 30-day daily summary. Returns `404` if the account doesn't exist. ```bash curl "https://app.warmerly.com/api/v1/accounts/1c2d3e4f-.../warmup-jobs" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "jobs": [ { "id": "9b1deb4d-....", "scheduledAt": "2026-07-02T08:00:00.000Z", "sentAt": "2026-07-02T08:00:42.000Z", "status": "processed", "senderAccountId": "1c2d3e4f-....", "recipientAccountId": "2d3e4f5a-....", "subject": "Re: quick question about the roadmap", "deliveredFolder": "inbox", "wasOpened": true, "wasReplied": false, "emailType": "reply" } ], "dailySummary": [ { "day": "2026-07-02", "sent": 22, "received": 19, "inbox": 20, "spam": 1 } ] } ``` `dailySummary` covers the trailing 30 days: `sent` and `received` count jobs where the account was sender/recipient respectively; `inbox`/`spam` count only processed jobs the account sent that landed in each folder. ## Pause and resume warmup on an account Warmup only runs against accounts with `status = active` or `aging`. Pausing an account stops it from being scheduled as a sender or recipient in future warmup jobs. ``` POST /accounts/{id}/pause POST /accounts/{id}/resume ``` Both take no request body and return `404` if the account doesn't exist. ```bash curl -X POST https://app.warmerly.com/api/v1/accounts/1c2d3e4f-.../pause \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "ok": true } ``` `resume` sets the account back to `active`, clears `needsReconnect` and `disconnectReason`, and resets `consecutiveFailures` to `0`: ```bash curl -X POST https://app.warmerly.com/api/v1/accounts/1c2d3e4f-.../resume \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "ok": true } ``` ## Mailbox health alerts ``` GET /alerts ``` The last 50 mailbox-health alerts raised for your account, newest first. These are the same events that trigger a health email, so polling this is the pull equivalent of [webhooks](https://docs.warmerly.com/webhooks) for anyone who would rather not run an endpoint. ```json { "alerts": [ { "id": "c3f1a2b4-5d6e-4f70-8a91-b2c3d4e5f607", "accountId": "3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10", "kind": "score_drop", "severity": "warning", "title": "Warmup health dropped for jane@yourdomain.com", "body": "Health score fell from 82 to 61 over the last 24 hours.", "scoreBefore": 82, "scoreAfter": 61, "sentAt": "2026-09-11T06:02:00.000Z", "createdAt": "2026-09-11T06:01:58.000Z" } ] } ``` | `kind` | Meaning | | --- | --- | | `score_drop` | Health score fell sharply. | | `score_floor` | Health score is below the acceptable floor. | | `oauth_disconnected` | A Google/Microsoft grant was revoked or expired, reconnect needed. | | `auth_fail` | SMTP/IMAP authentication is failing. | | `dns_changed` | The domain's SPF/DKIM/DMARC result changed since the last check. | | `domain_blocklisted` | The sending domain appeared on a public blocklist. | | `delivery_unobservable` | Mail is going out but nothing can be classified, so health cannot be measured at all. This is distinct from a bad score: there is no score. | `severity` is `info`, `warning` or `critical`. `sentAt` is when the notification went out (`null` if it has not been sent), as opposed to `createdAt`, when the condition was detected. ## Is warmup actually running? ``` GET /warmup/health ``` Whether Warmerly's warmup workers are alive. A plain authenticated caller gets the derived flag: ```json { "ok": true, "healthy": true } ``` `healthy` is `true` when the freshest worker heartbeat is under 10 minutes old. It is a platform-level answer, not a statement about your mailboxes: `healthy: true` with nothing sending means the problem is your campaign or mailbox configuration, and [`GET /campaigns/{id}/readiness`](https://docs.warmerly.com/campaigns#readiness-check) will say which. Staff callers additionally get `lastTick` per worker. `POST /warmup/run` exists but is ops-only: it triggers a planner/dispatcher pass across every workspace on the platform, so it returns `404` for a customer key. Warmup runs continuously on its own; there is nothing to trigger. ## Errors An account ID that doesn't exist returns `404` on any of the endpoints above: ```json { "error": { "code": "not_found", "message": "not_found", "details": null } } ``` Missing or invalid `X-Api-Key` returns `401`, following the same shape described in [Authentication](https://docs.warmerly.com/authentication). --- # Verify Check whether an email address is deliverable before you send to it, syntax, MX records, disposable/role-based detection, and a live SMTP probe, with results cached so repeat checks are free. Verify single addresses in real time, or submit a list as a bulk job for asynchronous processing. Verify endpoints are scoped to your **user account**, not a project, they don't require the `X-Project-Id` header. Single checks and bulk batches are recorded against your currently active workspace automatically. ## The verification object ```json { "email": "jane@example.com", "status": "valid", "confidence": 92, "reason": "smtp_accepted", "checks": { "syntax": true, "mx": ["aspmx.l.google.com"], "smtpConnectable": true, "smtpAccepted": true, "catchAll": false, "disposable": false, "roleBased": false, "freeProvider": false, "provider": "google", "didYouMean": null, "smtpCode": 250, "smtpMessage": "2.1.5 OK" }, "durationMs": 812, "checkedAt": "2026-07-02T10:14:03.000Z", "cached": false, "retryable": false } ``` | Field | Description | | --- | --- | | `status` | One of `valid`, `invalid`, `risky`, `catch_all`, `unknown`. | | `confidence` | 0-100 score. Used with `status` to decide whether the address is safe to send to. | | `reason` | Short machine-readable reason code (e.g. `smtp_accepted`, `mailbox_not_found`, `disposable_domain`). | | `checks` | The individual signals behind the `status`/`confidence`, syntax validity, MX records, SMTP connect/accept results, catch-all detection, disposable/role-based/free-provider flags, and the raw SMTP response. | | `cached` | `true` if this result was served from cache rather than a fresh SMTP probe. Cached results don't count against your quota. | | `retryable` | `true` if the check failed for a transient reason (e.g. SMTP timeout) and re-running with `force: true` may produce a different answer. | ## Verify a single email ``` POST /verify ``` Runs (or reuses a cached) verification for one address. Cached results are returned instantly and are **not billable**; a fresh check consumes one verification from your plan's quota. | Field | Type | Required | Description | | --- | --- | --- | --- | | `email` | string | Yes | The address to verify. | | `force` | boolean | No | Skip the cache and run a fresh SMTP probe even if a cached result exists. | ```bash curl https://app.warmerly.com/api/v1/verify \ -X POST \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "email": "jane@example.com" }' ``` ```json { "result": { "email": "jane@example.com", "status": "valid", "confidence": 92, "reason": "smtp_accepted", "checks": { "syntax": true, "mx": ["aspmx.l.google.com"], "smtpConnectable": true, "smtpAccepted": true, "catchAll": false, "disposable": false, "roleBased": false, "freeProvider": false, "provider": "google", "didYouMean": null, "smtpCode": 250, "smtpMessage": "2.1.5 OK" }, "durationMs": 812, "checkedAt": "2026-07-02T10:14:03.000Z", "cached": false, "retryable": false }, "checkId": "b2b7c9a0-1e3f-4a2b-9c1d-4e8f0a2b3c4d" } ``` Every call (cached or not) is saved to your [history](#verification-history) as `checkId`. Errors: `400 bad_request` for an invalid body, `402 payment_required` if you're out of verification quota. ```json { "error": { "code": "payment_required", "message": "quota_exceeded", "details": { "used": 5000, "limit": 5000 } } } ``` ## Bulk verification Submit a list of addresses as an asynchronous batch, then poll for results. Quota for the full batch size is checked up front, before any items are processed. ### Submit a batch ``` POST /verify/bulk ``` | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | No | Optional label for the batch. | | `emails` | string[] | No | Array of addresses. | | `text` | string | No | A pasted blob of addresses separated by whitespace, commas, or semicolons. | Provide `emails`, `text`, or both, they're merged and de-duplicated. A batch may contain at most 50,000 addresses. ```bash curl https://app.warmerly.com/api/v1/verify/bulk \ -X POST \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "name": "Q3 leads", "emails": ["jane@example.com", "john@example.com"] }' ``` ```json { "batch": { "id": "6f2c6c8e-9b1d-4e3a-9c7f-2d1e8b4a6c9e", "total": 2, "status": "processing" } } ``` `201 Created` on success. Errors: `400 bad_request` (`no_valid_emails` or `batch_too_large_max_50000`), `402 payment_required` (`quota_exceeded`, with `requested`/`used`/`limit`/`remaining` in `details`). ### Get batch status and results ``` GET /verify/bulk/{id} ``` Returns the batch's progress and, for items that have been processed, their verification results. ```bash curl https://app.warmerly.com/api/v1/verify/bulk/6f2c6c8e-9b1d-4e3a-9c7f-2d1e8b4a6c9e \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "batch": { "id": "6f2c6c8e-9b1d-4e3a-9c7f-2d1e8b4a6c9e", "name": "Q3 leads", "status": "processing", "total": 2, "processed": 1, "createdAt": "2026-07-02T10:00:00.000Z", "completedAt": null }, "items": [ { "email": "jane@example.com", "recommendation": "Safe to send", "status": "valid", "confidence": 92, "reason": "smtp_accepted" }, { "email": "john@example.com", "recommendation": "Pending", "status": null, "confidence": null, "reason": null } ] } ``` `batch.status` is `processing` or `completed`. Each item's `recommendation` is `Safe to send`, `Send with caution`, `Do not send`, `Unknown`, or `Pending` (not yet processed), a human-readable summary derived from `status`/`confidence`/`checks`. `404 not_found` if the batch doesn't exist or belongs to another user. Pass `?format=csv` to download the results as a CSV file (`email,recommendation,status,confidence,reason`) instead of JSON: ```bash curl "https://app.warmerly.com/api/v1/verify/bulk/6f2c6c8e-9b1d-4e3a-9c7f-2d1e8b4a6c9e?format=csv" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -o results.csv ``` ## Verification history ``` GET /verify/history ``` Returns your recent single verifications (from `POST /verify`), most recent first, cursor-paginated. | Query param | Type | Required | Description | | --- | --- | --- | --- | | `cursor` | ISO 8601 timestamp | No | Fetch results older than this timestamp. Use the previous response's `nextCursor`. | | `limit` | integer | No | Page size, 1-100. Default `25`. | ```bash curl "https://app.warmerly.com/api/v1/verify/history?limit=25" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "checks": [ { "id": "b2b7c9a0-1e3f-4a2b-9c1d-4e8f0a2b3c4d", "email": "jane@example.com", "status": "valid", "confidence": 92, "reason": "smtp_accepted", "checks": { "...": "..." }, "confirmedStatus": null, "sendTestStatus": null, "createdAt": "2026-07-02T10:14:03.000Z" } ], "nextCursor": "2026-07-02T09:58:11.000Z" } ``` `confirmedStatus` and `sendTestStatus` reflect a follow-up bounce-probe test send kicked off from the dashboard to confirm an uncertain SMTP result (`valid` or `invalid` once resolved); both are `null` if no test was run. `nextCursor` is `null` once you've reached the end of history. ## Send test (deliverability-grade check) Some addresses cannot be settled by SMTP probing alone, a catch-all domain accepts everything, so "accepted" proves nothing. A send test resolves those the only way that actually works: it sends one real message from one of your own warmup mailboxes and watches for a bounce. ``` POST /verify/send-test GET /verify/send-test/{id} ``` | Field | Type | Required | Description | | --- | --- | --- | --- | | `email` | string | Yes | Address to test. | | `checkId` | string (UUID) | No | Links the result back to an earlier verification, so the original check is refined rather than duplicated. | ```json { "test": { "id": "9f1c2d3e-4a5b-4c6d-8e7f-0a1b2c3d4e5f", "email": "sam@example.com", "status": "awaiting_bounce", "fromAccount": "jane@yourdomain.com", "bounceCode": null, "bounceMessage": null, "failureReason": null, "deadlineAt": "2026-09-12T10:15:00.000Z" } } ``` `GET /verify/send-test/{id}` is the poll: each call does a throttled IMAP check for the bounce and returns the current `status`, `awaiting_bounce`, `valid`, `invalid` or `failed`. The watch window is about five minutes (`deadlineAt`). A bounce inside it makes the test `invalid`. A reply from the address, or reaching `deadlineAt` with no bounce, makes it `valid`. So `valid` here means "no bounce came back in the window", not proof the mailbox is read. A poll made after `deadlineAt` is what settles the test, so keep polling until the status is no longer `awaiting_bounce`. Notes worth knowing before you wire this up: - It requires a connected sending mailbox. With none, the test comes back immediately as `failed` with `failureReason: "no_account"` rather than erroring. - It sends **real email from your mailbox**, so it affects that mailbox's reputation like any other send. Use it to settle a handful of ambiguous addresses, not as a bulk strategy. - It is **not** billed as a separate verification. It refines a check that was already counted. ## Usage / quota ``` GET /verify/usage ``` Returns your current verification usage against your plan's limit for the billing period. Checking usage does not itself consume quota. ```bash curl https://app.warmerly.com/api/v1/verify/usage \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "usage": { "used": 128, "limit": 500, "remaining": 372, "plan": "growth" } } ``` --- # Email Finder Find and verify a person's or company's email address from a domain, website, or business name, optionally narrowed to a specific person. Lookups run asynchronously as **jobs**: most resolve in a few seconds, but cache misses can take longer while Warmerly scrapes and verifies candidates, so the API returns immediately with either a completed result or a job you poll. All Email Finder endpoints require `X-Api-Key`. Endpoints that create or read job data are project-scoped and also require `X-Project-Id`; `GET /email-finder/quota` is account-level and does not require `X-Project-Id`. ## Single lookup ``` POST /email-finder/lookup ``` Submit one lookup. Provide at least one of `domain`, `website`, or `name`, add `person` to narrow the search to a specific individual at that domain/company. | Field | Type | Description | | --- | --- | --- | | `domain` | string | Company domain, e.g. `"acme.com"`. | | `website` | string | Full website URL; the domain is extracted from it. | | `name` | string | Business name, used when no domain/website is known. | | `location` | string | Optional location hint to disambiguate a business name. | | `person.firstName` | string | Optional first name to target a specific person. | | `person.lastName` | string | Optional last name to target a specific person. | ```bash curl https://app.warmerly.com/api/v1/email-finder/lookup \ -X POST \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" \ -H "Content-Type: application/json" \ -d '{ "domain": "acme.com", "person": { "firstName": "Jane", "lastName": "Doe" } }' ``` If the answer is already cached, the lookup completes synchronously and returns `200` with the result inline: ```json { "status": "done", "jobId": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10", "job": { "id": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10", "status": "done", "confidence": 92, "error": null, "createdAt": "2026-07-02T09:14:03.000Z", "completedAt": "2026-07-02T09:14:03.000Z" }, "result": { "email": "jane.doe@acme.com", "confidence": 92, "verifyStatus": "verified", "source": "pattern_guess", "isCatchAll": false, "mxHost": "aspmx.l.google.com", "evidenceUrl": "https://acme.com/team", "providerName": "Google Workspace" } } ``` Otherwise it enqueues a job and returns `202` with a `pollUrl`: ```json { "status": "pending", "jobId": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10", "pollUrl": "https://app.warmerly.com/api/v1/email-finder/jobs/3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10" } ``` Poll the job (see below) until `status` is `"done"` or `"failed"`. ## Bulk lookup ``` POST /email-finder/bulk ``` Submit up to 1,000 lookups in one request. Each item accepts the same fields as a single lookup. All items are enqueued under a shared `batchId` you can use to track progress via [Batches](#batch-status). ```bash curl https://app.warmerly.com/api/v1/email-finder/bulk \ -X POST \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" \ -H "Content-Type: application/json" \ -d '{ "items": [ { "domain": "acme.com", "person": { "firstName": "Jane", "lastName": "Doe" } }, { "website": "https://widgetco.io" }, { "name": "Roasted Coffee Co", "location": "Austin, TX" } ] }' ``` ```json { "batchId": "6e6f9d0a-4a3f-4c7e-9c86-1b6a4e5c2f01", "results": [ { "index": 0, "ok": true, "jobId": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10", "cached": true, "result": { "email": "jane.doe@acme.com", "confidence": 92, "verifyStatus": "verified", "source": "pattern_guess", "isCatchAll": false, "mxHost": "aspmx.l.google.com", "evidenceUrl": "https://acme.com/team", "providerName": "Google Workspace" } }, { "index": 1, "ok": true, "jobId": "7c1e9b3d-8a2f-4e11-9d0c-5b3a1f4e6c22", "cached": false }, { "index": 2, "ok": false, "error": "invalid input" } ] } ``` Each item is evaluated independently: an invalid item (`ok: false`) does not fail the rest of the batch. Items that hit the cache resolve immediately (`cached: true`, `result` present); the rest are enqueued (`cached: false`) and must be polled individually via their `jobId`, or tracked in aggregate via batch status. ## Get a job ``` GET /email-finder/jobs/:id ``` Fetch the current status of a lookup job, whether it came from a single or bulk request. ```bash curl https://app.warmerly.com/api/v1/email-finder/jobs/3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10 \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" ``` ```json { "job": { "id": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10", "status": "scraping", "confidence": null, "error": null, "createdAt": "2026-07-02T09:14:03.000Z", "completedAt": null }, "result": null } ``` `status` moves through `pending` → `resolving` → `scraping` → `verifying` → `done` (or `failed`). `result` is populated once `status` is `"done"`; on `"failed"`, check `job.error` for the reason. A job for a project you don't have access to (or that doesn't exist) returns `404`. ## Delete a job ``` DELETE /email-finder/jobs/:id ``` Deletes the job and its discovered email records. ```bash curl https://app.warmerly.com/api/v1/email-finder/jobs/3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10 \ -X DELETE \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" ``` ```json { "deleted": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10" } ``` ## Batch status ``` GET /email-finder/batches/:id ``` Returns aggregate progress for a bulk lookup, grouped by job status. ```bash curl https://app.warmerly.com/api/v1/email-finder/batches/6e6f9d0a-4a3f-4c7e-9c86-1b6a4e5c2f01 \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" ``` ```json { "batchId": "6e6f9d0a-4a3f-4c7e-9c86-1b6a4e5c2f01", "total": 3, "done": 2, "pending": 1, "counts": { "done": 2, "scraping": 1 } } ``` `done` sums jobs in either `done` or `failed` status. Use [List results](#list-results) with `batchId` to fetch the actual emails once a batch is complete. ## List results ``` GET /email-finder/results ``` Lists jobs for the current project, each joined with its winning discovered email (if any), newest first. Cursor-paginated. | Query param | Type | Description | | --- | --- | --- | | `status` | string | Filter by job status: `pending`, `resolving`, `scraping`, `verifying`, `done`, `failed`. | | `batchId` | uuid | Restrict to jobs from a specific bulk batch. | | `minConfidence` | integer (0-100) | Only include results with confidence at or above this value. | | `cursor` | ISO 8601 datetime | Pass the previous response's `nextCursor` to fetch the next page. | | `limit` | integer (1-100, default 25) | Page size. | ```bash curl "https://app.warmerly.com/api/v1/email-finder/results?status=done&limit=25" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" ``` ```json { "results": [ { "id": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10", "status": "done", "confidence": 92, "inputDomain": "acme.com", "inputName": null, "batchId": null, "createdAt": "2026-07-02T09:14:03.000Z", "email": "jane.doe@acme.com", "verifyStatus": "verified", "source": "pattern_guess" } ], "nextCursor": "2026-07-02T09:14:03.000Z" } ``` Pass `nextCursor` as the `cursor` query param to fetch the next page; it is `null` on the last page. ## Quota ``` GET /email-finder/quota ``` Returns your current monthly Email Finder usage. This endpoint is account-level, it does not require `X-Project-Id`. ```bash curl https://app.warmerly.com/api/v1/email-finder/quota \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "used": 37, "limit": 500, "remaining": 463 } ``` Free-trial workspaces default to 50 lookups/month; paid plans raise the limit. Both `POST /email-finder/lookup` and `POST /email-finder/bulk` check remaining quota before enqueuing, a bulk request counts against quota by item count. If the request would exceed your limit, it's rejected with `400`: ```json { "error": { "code": "bad_request", "message": "plan_limit_reached", "details": { "allowed": false, "used": 500, "limit": 500, "remaining": 0, "plan": "growth" } } } ``` ## Errors | Status | Code | When | | --- | --- | --- | | `400` | `bad_request` | Missing `X-Project-Id` (project-scoped endpoints), invalid body/query, no valid `domain`/`website`/`name` provided, or quota exhausted (`*_limit_reached`). | | `401` | `unauthorized` | Missing, invalid, or revoked API key. | | `404` | `not_found` | Job or batch doesn't exist, or doesn't belong to the given project. | | `429` | `too_many_requests` | Rate limit exceeded. | --- # Leads The Leads API searches Warmerly's crawled company database and lets you export matches to CSV or push them straight into a campaign's audience. It's scoped to your **user account** (not a project), search results and export quota are shared across every project you own. Suppressed companies are always excluded, at search time and again at export/push time. All endpoints below require `X-Api-Key` and do **not** read `X-Project-Id`. ## The company object ```json { "id": "b1e6a2c4-9f3d-4a7e-8c1b-2d5f9a3e7c6b", "domain": "northwindtraders.com", "companyName": "Northwind Traders", "legalName": "Northwind Traders Ltd", "description": "Wholesale importer of specialty foods.", "websiteUrl": "https://northwindtraders.com", "country": "GB", "city": "Manchester", "region": "Greater Manchester", "streetAddress": "14 Dock Street", "postalCode": "M1 2AB", "phone": "+441611234567", "orgType": "Wholesaler", "industry": null, "techStack": ["shopify", "klaviyo"], "emailProvider": "google", "linkedinUrl": "https://www.linkedin.com/company/northwind-traders", "twitterUrl": null, "socialUrls": ["https://www.facebook.com/northwindtraders"], "contactEmail": "info@northwindtraders.com", "allEmails": ["info@northwindtraders.com", "sales@northwindtraders.com"], "crawledAt": "2026-08-10T04:22:00.000Z" } ``` `contactEmail` is the first of `allEmails`, kept separate because export and push-to-campaign both key off a single address per company. Deliverability signals (MX/SPF/DMARC) are deliberately not exposed on this object, they're Warmerly's own outreach data, not customer-facing. ## Search companies ``` GET /leads/search ``` | Query param | Type | Required | Description | | --- | --- | --- | --- | | `q` | string (max 200) | No | Full-text search across company name, description, and other indexed fields. | | `country` | string (2-letter) | No | ISO country code, e.g. `GB`. | | `category` | string | No | One or more categories, comma-separated (e.g. `Restaurant,CafeOrCoffeeShop`). | | `provider` | string | No | Email provider segment, e.g. `google`, `microsoft`. | | `tech` | string | No | One or more technologies, comma-separated (e.g. `shopify,klaviyo`), matches companies using **any** of them. | | `channel` | `"email"` \| `"form"` \| `"linkedin"` | No | Which contact channel a company must have. **Defaults to `email`**: a company with no published contact address is never returned unless you ask for a different channel. `form` returns companies publishing a contact form, `linkedin` those with a company page. There is no value that removes the requirement. | | `hasPhone` | `"true"` | No | Only companies publishing a telephone number. | | `hasCompanyNumber` | `"true"` | No | Only companies publishing a Companies House registration number, in practice, UK-registered. | | `hasVatNumber` | `"true"` | No | Only companies publishing a VAT number. | | `hiring` | `"true"` | No | Only companies linking a careers page or stating they are hiring. | | `hasContactForm` | `"true"` | No | Only companies publishing a contact form URL. | | `city` | string (max 120) | No | Town or city, matched through the same text index as `q`. | | `employeeBand` | string | No | One coarse size band, e.g. `11-50`. | | `foundedFrom` / `foundedTo` | integer | No | Inclusive founded-year range. | | `cursor` | string (UUID) | No | Pass the previous response's `nextCursor` to fetch the next page. | | `limit` | integer (1-100) | No | Page size. Default `50`. | ```bash curl "https://app.warmerly.com/api/v1/leads/search?country=GB&category=Restaurant&tech=shopify&limit=25" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "rows": [ { "id": "b1e6a2c4-9f3d-4a7e-8c1b-2d5f9a3e7c6b", "domain": "northwindtraders.com", "companyName": "Northwind Traders", "country": "GB", "contactEmail": "info@northwindtraders.com", "techStack": ["shopify", "klaviyo"] } ], "nextCursor": "b1e6a2c4-9f3d-4a7e-8c1b-2d5f9a3e7c6b", "countLabel": "312", "coverage": { "sampleSize": 312, "exact": true, "email": 312, "phone": 190, "companyNumber": 141, "contactForm": 88, "linkedin": 97, "country": 305 } } ``` `coverage` reports how many of the matching companies carry each high-value field, so you can see how complete a segment is before you export it. It is measured over at most 1,000 matching rows: when `exact` is `true` the sample was the entire result set and these are counts; when it is `false` more rows match than were measured and the figures are a `sampleSize`-row sample, not totals. The whole table is never aggregated. `countLabel` is an exact count below 1,000 matches, and the literal string `"1000+"` above that, matching results are never counted with an unbounded `COUNT(*)` over the full table. `nextCursor` is present whenever there may be more rows; keep paging with it until a response returns fewer rows than `limit`. This endpoint has its own per-user throttle, separate from your API key's per-minute rate limit, see [Rate limits](#rate-limits--errors) below. ## Match count ``` GET /leads/count ``` `countLabel` on a search response tops out at `"1000+"`, because counting inside a search request would make the search slow for everyone. When you need a real number for a segment, to size an export, or to show "312 matches" in a UI, ask for it separately. Takes exactly the same filter params as [search](#search-companies), minus paging. ```bash curl "https://app.warmerly.com/api/v1/leads/count?country=GB&hasEmail=true" -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "count": { "value": 118520, "exact": true, "capped": false, "wasCountable": true }, "coverage": { "sampleSize": 1000, "exact": false, "email": 1000, "phone": 612, "companyNumber": 455, "contactForm": 288, "linkedin": 331, "country": 1000 } } ``` | Field | Description | | --- | --- | | `count.value` | The number to show. | | `count.exact` | `true` when the rows were actually counted, `false` when the figure is a planner **estimate**. Word these differently: estimates on this table run low, so presenting one as a count understates most segments several-fold. | | `count.capped` | Only with `exact: true`. The count stopped at a hard row ceiling, so `value` is a floor and the real total is larger. | | `count.exact: false` | Expected on broad segments. A narrow filter gets counted, a country-wide one gets estimated, and an estimate is the intended answer rather than a failure. | `coverage` is the same field-completeness breakdown search returns, measured over at most 1,000 matching rows (`exact: false` there means it is a sample, not totals). ## Database size ``` GET /leads/totals ``` How many companies the lead database currently holds. The crawl adds rows continuously, so these figures move. ```json { "emailable": 4677084, "total": 13914447, "approximate": true, "asOf": "2026-08-21T15:41:02.000Z" } ``` | Field | Description | | --- | --- | | `emailable` | Companies with a published contact email that are not suppressed, the population `GET /leads/search` draws from by default. | | `total` | All company records held, contactable or not. | | `approximate` | Always `true`. | | `asOf` | When the snapshot was taken. | Both figures are **estimates**, derived from the database's own planner statistics rather than by counting rows, and may be a few minutes behind on a table this size. Treat them as "about N", never as an exact count. Either figure can be `null` if the statistic is unavailable. ## Export to CSV ``` POST /leads/export ``` Exports matching companies as a CSV file (download, not JSON). Debits your monthly lead export quota by the number of rows actually delivered, not the number you asked for. Select rows with **one** of two shapes in the request body: | Field | Type | Required | Description | | --- | --- | --- | --- | | `domains` | string[] (1-10,000) | One of `domains`/`selectAllMatching` | Explicit list of domains to export. | | `filters` | object | No | Same filter shape as [search](#search-companies) (`q`, `country`, `category`, `provider`, `tech`, `channel`, `hasPhone`, and the firmographic filters). Booleans are JSON booleans here, not the strings the query string uses. Used with `selectAllMatching`. The `channel` default applies here too: an export never contains a company you cannot contact by email unless you named another channel. | | `selectAllMatching` | `true` | One of `domains`/`selectAllMatching` | Export every row matching `filters`, re-resolved server-side. | The CSV export streams and has no per-request row cap: it stops when the rows run out or your monthly export allowance does. The `domains` list is limited to 10,000 entries per request. [Push to campaign](#push-to-a-campaign) is capped at 10,000 rows per request. ```bash curl -X POST https://app.warmerly.com/api/v1/leads/export \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "filters": { "country": "GB", "tech": ["shopify"] }, "selectAllMatching": true }' \ -o leads.csv ``` Returns `200` with `content-type: text/csv`. The response also carries an `X-Lead-Count` header with the exact row count in the file (CORS-exposed, so browser `fetch()` can read it), this can be lower than what you selected, because suppression and the "has an email" filter are re-applied at export time. CSV columns, in order: ``` domain, company_name, legal_name, website_url, country, city, category, tech_stack, email, all_emails, phone, street_address, region, postal_code, linkedin_url, twitter_url, other_social, mail_provider, description, last_checked ``` New columns may be appended in future; existing columns won't be reordered or removed. Errors: `400 bad_request` (`no_selection` if neither `domains` nor `selectAllMatching` is set, `invalid_export_request` for a malformed body), `402 payment_required` if the request would exceed your monthly export quota: ```json { "error": { "code": "payment_required", "message": "Lead export limit reached: 480/500 used this month.", "details": null } } ``` ## Push to a campaign ``` POST /leads/to-campaign ``` Same selection shape as [export](#export-to-csv), plus a target campaign. It adds matching companies directly to a campaign's audience instead of downloading a file and debits the same monthly export quota as CSV export (the two share one meter). | Field | Type | Required | Description | | --- | --- | --- | --- | | `campaignId` | string (UUID) | Yes | The campaign to add leads to. | | `domains` | string[] (1-10,000) | One of `domains`/`selectAllMatching` | Explicit list of domains to add. | | `filters` | object | No | Same filter shape as [search](#search-companies). Used with `selectAllMatching`. | | `selectAllMatching` | `true` | One of `domains`/`selectAllMatching` | Add every row matching `filters`. | ```bash curl -X POST https://app.warmerly.com/api/v1/leads/to-campaign \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "campaignId": "3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10", "domains": ["northwindtraders.com"] }' ``` ```json { "added": 1, "skipped": 0 } ``` `skipped` counts rows that were dropped because they had no contact email or were already in the campaign's audience (deduplicated by lowercased email), those don't count against your quota. Errors mirror [export](#export-to-csv)'s `400`/`402` cases, plus `404 not_found` for an unknown `campaignId` and `402 billing_locked` if the campaign's workspace has a billing issue. ## LinkedIn people search ``` GET /linkedin/search GET /linkedin/search/parameters ``` A different database to the company search above: this queries **LinkedIn** through your own connected LinkedIn account, so it needs a paid LinkedIn slot and a connected account (`400 no_linkedin_account` otherwise). | Query param | Type | Description | | --- | --- | --- | | `query` | string | **Required.** Keywords. | | `cursor` | string | Next page, from the previous response's `cursor`. | | `locationIds` | comma-separated integers | LinkedIn location facet IDs. | | `industryIds` | comma-separated integers | LinkedIn industry facet IDs. | | `companyIds` | comma-separated integers | LinkedIn company facet IDs. | | `networkDistance` | comma-separated integers | 1st / 2nd / 3rd degree. | | `profileLanguage` | comma-separated strings | Profile language codes. | The facet filters take LinkedIn's own numeric IDs, not names. `GET /linkedin/search/parameters?type=LOCATION|INDUSTRY|COMPANY&keywords=…` is the typeahead that resolves a name into those IDs, returning `{ "items": [{ "id": "…", "title": "…" }] }`. ```json { "items": [ { "id": "ACoAAA…", "public_identifier": "samexample", "name": "Sam Example", "headline": "Head of Growth at Example Ltd", "location": "London, United Kingdom", "company_name": "Example Ltd", "profile_url": "https://www.linkedin.com/in/samexample", "network_distance": "DISTANCE_2", "email": null, "phone": null } ], "cursor": "eyJwYWdlIjoyfQ" } ``` **One LinkedIn lookup is charged per search page, not per profile returned** — paging with `cursor` issues a fresh upstream call, which is the unit of real cost. A search that fails or is rejected costs nothing: the allowance is debited only after results come back. Out of allowance returns `402 payment_required` with `used`, `limit` and `remaining`. `email` and `phone` are populated only when the profile lists them publicly and they are visible to your account, usually they are `null`, which is what [`POST /campaigns/{id}/leads/find-emails`](https://docs.warmerly.com/campaigns) and the [Email Finder](https://docs.warmerly.com/email-finder) are for. ## Export quota ``` GET /leads/quota ``` Returns your current lead-export usage for the billing period. A pure read, checking it never debits quota. ```bash curl https://app.warmerly.com/api/v1/leads/quota \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "used": 480, "limit": 500, "remaining": 20 } ``` ## Rate limits & errors `GET /leads/search` has its own throttle on top of your API key's per-minute limit: **120 requests per 5 minutes, per user** (not per key or IP). Exceeding it returns `429 too_many_requests`. See [Errors & Rate Limits](https://docs.warmerly.com/errors) for the shared error envelope and your key's general per-minute limit. --- # Inbox The Inbox API exposes Warmerly's unified inbox, every email, LinkedIn DM, and WhatsApp message tied to a contact, in one place. Use it to list contacts, pull a full conversation timeline, and send replies across channels. Inbox endpoints only need `X-Api-Key`. They do **not** read `X-Project-Id`, unlike most other resources, the inbox is scoped to your **active workspace** (the same one selected in the dashboard), which can span multiple projects at once. If you're a member of more than one workspace, requests use whichever workspace is currently active on your account. ```bash curl https://app.warmerly.com/api/v1/inbox/contacts \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ## List contacts ``` GET /inbox/contacts ``` Returns every inbox contact in your active workspace, the people/companies you've exchanged messages with across email, LinkedIn, and WhatsApp, newest activity first. | Query param | Required | Description | | --- | --- | --- | | `workspaceId` | No | Filter to contacts belonging to a single project. Despite the name, this is a project ID (the inbox filter bar labels projects as "workspaces"). | | `accountId` | No | Filter to contacts with at least one message sent/received via this account (email account today). | | `q` | No | Search contact name/email/phone/company and message content (subject, body, sender). Terms match by prefix. | | `needsReply` | No | `true`, only conversations classified as a lead whose newest message is inbound. | | `archived` | No | `true`, only conversations where every message is archived. | | `unread` | No | `true`, only conversations with at least one unread inbound message. | | `category` | No | `lead`, `not_relevant`, or `spam`. | | `channel` | No | `email`, `linkedin`, or `whatsapp`. | | `limit` | No | Page size, 1-200 (default 50). | | `offset` | No | Page offset (default 0). | All filters are applied before pagination, so `total` is the real number of matching conversations and paging through with `offset` reaches every one of them. ```bash curl "https://app.warmerly.com/api/v1/inbox/contacts?accountId=8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "contacts": [ { "id": "c3a1f6e2-9c4d-4e2a-8b5f-6a2c1d9e0f7b", "name": "Jamie Rivera", "company": "Northwind Traders", "avatarUrl": null, "email": "jamie@northwindtraders.com", "phone": "+15551234567", "hasWhatsapp": true, "linkedinProfileUrl": "https://www.linkedin.com/in/jamierivera", "channels": ["email", "linkedin"], "lastActivityAt": "2026-07-01T16:42:03.000Z", "hasUnread": true, "lastPreview": "Thanks for reaching out, can we do a call next week?", "category": "lead", "categoryReason": "Replied positively and asked to schedule a call" } ], "total": 128, "hasMore": true } ``` | Field | Type | Description | | --- | --- | --- | | `id` | string (UUID) | Contact ID, use this for the timeline and reply endpoints. | | `name` | string | Display name, falling back to email or phone if unset. | | `company` | string \| null | Company name, when known from an associated campaign lead. | | `email` | string \| null | Contact's email address. | | `phone` | string \| null | Contact's phone number, when known. | | `hasWhatsapp` | boolean | True if the contact has a phone number **or** a raw WhatsApp JID on file. Use this (not `phone`) to decide whether a WhatsApp reply is possible. | | `linkedinProfileUrl` | string \| null | LinkedIn profile URL, when known. | | `channels` | array | Channels (`email`, `linkedin`, `whatsapp`) this contact has any message on. | | `lastActivityAt` | string | ISO 8601 timestamp of the most recent message. | | `hasUnread` | boolean | True if there's at least one unread inbound message. | | `lastPreview` | string \| null | Snippet of the most recent message. | | `category` | `"lead"` \| `"not_relevant"` \| `"spam"` \| null | AI/rule-assigned triage category. | | `categoryReason` | string \| null | Short explanation for the assigned category. | ## Get a contact's timeline ``` GET /inbox/contacts/{contactId}/timeline ``` Returns the full conversation with a contact across all channels, in chronological order, plus any autosaved email draft in progress for the latest inbound thread. ```bash curl https://app.warmerly.com/api/v1/inbox/contacts/c3a1f6e2-9c4d-4e2a-8b5f-6a2c1d9e0f7b/timeline \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "items": [ { "id": "9d1e0b7a-5e7b-4f10-b2aa-1c8f0d3e6a4b", "channel": "email", "direction": "inbound", "status": "sent", "content": "Hi, thanks for the intro, happy to learn more.", "bodyHtml": "

Hi, thanks for the intro, happy to learn more.

", "subject": "Re: Quick question about your workflow", "sentAt": "2026-06-30T11:05:00.000Z", "fromAddr": "jamie@northwindtraders.com", "fromName": "Jamie Rivera", "toAddrs": ["you@yourcompany.com"], "externalId": null, "error": null }, { "id": "7f3a2cdb-9e1a-4f0c-8b6d-2e5f7a1c3b9d", "channel": "email", "direction": "outbound", "status": "sent", "content": "Great, does Tuesday at 3pm work for a quick call?", "bodyHtml": null, "subject": "Re: Quick question about your workflow", "sentAt": "2026-07-01T16:42:03.000Z", "fromAddr": "you@yourcompany.com", "fromName": "Your Name", "toAddrs": ["jamie@northwindtraders.com"], "externalId": null, "error": null } ], "draft": null, "contact": { "id": "c3a1f6e2-9c4d-4e2a-8b5f-6a2c1d9e0f7b", "category": "lead", "categoryReason": "Replied positively and asked to schedule a call" } } ``` | Field | Type | Description | | --- | --- | --- | | `items[].channel` | `"email"` \| `"linkedin"` \| `"whatsapp"` | Channel the message was sent/received on. | | `items[].direction` | `"inbound"` \| `"outbound"` | Who sent it. | | `items[].status` | `"queued"` \| `"sent"` \| `"failed"` | Delivery status (WhatsApp sends start `queued` until the worker delivers them). | | `items[].content` | string | Plain-text body (falls back to snippet if the full body wasn't stored). | | `draft` | object \| null | Autosaved email draft for the latest inbound email thread, if one exists (`subject`, `bodyText`). | If `contactId` doesn't exist, or belongs to a contact outside your active workspace, this returns `404`: ```json { "error": { "code": "not_found", "message": "not_found", "details": null } } ``` ## Reply to a contact ``` POST /inbox/contacts/{contactId}/reply ``` Sends a reply to a contact on a specific channel and appends it to the timeline. Each channel has its own requirements: | Field | Type | Required | Description | | --- | --- | --- | --- | | `channel` | `"email"` \| `"linkedin"` \| `"whatsapp"` | Yes | Channel to send on. | | `body` | string | Yes | Message text. | | `subject` | string | Email only | Required when `channel` is `"email"`. | | `sourceAccountId` | string | Yes | ID of the connected account to send from (email account, LinkedIn account, or WhatsApp account, matching `channel`). | ```bash curl -X POST https://app.warmerly.com/api/v1/inbox/contacts/c3a1f6e2-9c4d-4e2a-8b5f-6a2c1d9e0f7b/reply \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "channel": "email", "subject": "Re: Quick question about your workflow", "body": "Great, does Tuesday at 3pm work for a quick call?", "sourceAccountId": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" }' ``` ```json { "message": { "id": "7f3a2cdb-9e1a-4f0c-8b6d-2e5f7a1c3b9d", "channel": "email", "direction": "outbound", "status": "sent", "contactId": "c3a1f6e2-9c4d-4e2a-8b5f-6a2c1d9e0f7b", "accountId": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "subject": "Re: Quick question about your workflow", "bodyText": "Great, does Tuesday at 3pm work for a quick call?", "toAddrs": ["jamie@northwindtraders.com"], "fromAddr": "you@yourcompany.com", "receivedAt": "2026-07-01T16:42:03.000Z" } } ``` Notes on behavior by channel: - **Email** sends synchronously over SMTP; the contact must have an `email` on file and `subject` is required. A send failure returns `500` with the SMTP error message, but the failed message is still recorded in the timeline with `status: "failed"`. - **LinkedIn** sends synchronously via Unipile; the contact must have a `linkedinProfileId` on file. - **WhatsApp** is sent asynchronously: the message is inserted with `status: "queued"` and delivered by a background worker shortly after. The contact must have a phone number or WhatsApp JID on file. Missing channel-specific data returns `400`, e.g.: ```json { "error": { "code": "bad_request", "message": "contact_has_no_email", "details": null } } ``` ## List threads ``` GET /inbox/threads ``` Returns email threads (grouped by `threadKey` + `accountId`) with aggregate counts, for building a mailbox-style view. This is account/folder-oriented, as opposed to `/inbox/contacts`, which is contact-oriented and spans channels. | Query param | Required | Description | | --- | --- | --- | | `accountId` | No | Filter to a single email account. | | `folder` | No | IMAP folder to filter by. Defaults to `INBOX`. Ignored unless `view` is `inbox`. | | `view` | No | One of `inbox` (default), `archived`, `starred`, `sent`. | | `q` | No | Full-text search across subject, sender, and body (Postgres FTS with an ILIKE fallback). | | `limit` | No | Max threads to return, `1` to `100`. Defaults to `50`. | ```bash curl "https://app.warmerly.com/api/v1/inbox/threads?accountId=8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a&view=inbox&limit=20" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "threads": [ { "threadKey": "", "accountId": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "lastReceivedAt": "2026-07-01T16:42:03.000Z", "messageCount": 4, "unreadCount": 1, "starred": false, "lastFromAddr": "jamie@northwindtraders.com", "lastFromName": "Jamie Rivera", "lastSubject": "Re: Quick question about your workflow", "lastSnippet": "Great, does Tuesday at 3pm work for a quick call?" } ] } ``` ## Get a thread ``` GET /inbox/threads/{key} ``` Returns every raw message in a single email thread, chronological order. `{key}` is the `threadKey` from `/inbox/threads` (URL-encode it, thread keys are typically `Message-Id`-style strings and contain special characters). | Query param | Required | Description | | --- | --- | --- | | `accountId` | No | Narrow to messages on this account (recommended, since thread keys aren't guaranteed unique across accounts). | ```bash curl "https://app.warmerly.com/api/v1/inbox/threads/%3CCADx...%40mail.gmail.com%3E?accountId=8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "messages": [ { "id": "9d1e0b7a-5e7b-4f10-b2aa-1c8f0d3e6a4b", "accountId": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "folder": "INBOX", "threadKey": "", "fromAddr": "jamie@northwindtraders.com", "fromName": "Jamie Rivera", "toAddrs": ["you@yourcompany.com"], "subject": "Re: Quick question about your workflow", "bodyText": "Hi, thanks for the intro, happy to learn more.", "isRead": true, "isStarred": false, "isArchived": false, "channel": "email", "direction": "inbound", "status": "sent", "receivedAt": "2026-06-30T11:05:00.000Z" } ] } ``` This endpoint returns raw `inbox_messages` rows (unfiltered by workspace/project ownership) rather than the trimmed shape used by the timeline endpoint, scope your query with `accountId` to keep results to accounts you control. ## Filter options ``` GET /inbox/filter-options ``` Returns the projects and email accounts available to filter the inbox by, for populating a workspace/account picker in your own UI. ```bash curl https://app.warmerly.com/api/v1/inbox/filter-options \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "workspaces": [ { "id": "b2f4a6c1-3e5d-4f7a-9b1c-0d2e4f6a8c1b", "name": "Marketing outreach" } ], "accounts": [ { "id": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "email": "you@yourcompany.com", "provider": "gmail", "projectId": "b2f4a6c1-3e5d-4f7a-9b1c-0d2e4f6a8c1b" } ] } ``` `workspaces` here is a list of **projects** within your active workspace (the `workspaceId` query param used elsewhere in this API is a project ID, see the note under [List contacts](#list-contacts)). ## Other endpoints These cover more specialized inbox workflows and are not detailed here: | Endpoint | Description | | --- | --- | | `POST /inbox/compose` | Start a new (non-reply) conversation over email, LinkedIn, or WhatsApp. | | `POST /inbox/sync` | Trigger an IMAP sync for one account (`?accountId=`) or all connected accounts. | | `POST /inbox/contacts/{contactId}/draft-reply` | Generate an AI draft reply for a contact's latest inbound email and autosave it. | | `GET/POST /inbox/drafts`, `PATCH/DELETE /inbox/drafts/{id}` | Manually saved (non-autosaved) email drafts. `GET` requires `?accountId=`, a draft belongs to one mailbox, so there is no cross-mailbox listing. | | `POST /inbox/mark-all-read` | Mark unread inbound messages as read. Pass `contactIds` (up to 500) to mark just those conversations, or omit it to mark the whole workspace inbox. Returns `{ "marked": n }`. | | `GET /inbox/warmup-jobs` | Warmup job activity feed for the inbox view. | | `PATCH/DELETE /inbox/messages/{id}` | Update flags on (read/starred/archived), or delete, a single message. | | `GET /inbox/messages/{id}/attachments/{part}` | Download a specific email attachment part. | --- # Transactional email Send your application's own email through Warmerly: password resets, receipts, sign-in links and notifications. The same product that warms up your cold outreach also delivers the mail your users are waiting for. Plans start free; prices, allowances and what counts as one email are on the [transactional email pricing page](https://warmerly.com/transactional-email#pricing). Moving from another provider? The comparisons for [Resend](https://warmerly.com/transactional-email/resend-alternative), [SendGrid](https://warmerly.com/transactional-email/sendgrid-alternative), [Postmark](https://warmerly.com/transactional-email/postmark-alternative) and [Amazon SES](https://warmerly.com/transactional-email/amazon-ses-alternative) map their request fields to these. Starting from a framework? There are working examples for [Node.js](https://warmerly.com/transactional-email/integrations/nodejs), [Next.js](https://warmerly.com/transactional-email/integrations/nextjs), [Django](https://warmerly.com/transactional-email/integrations/django), [Laravel](https://warmerly.com/transactional-email/integrations/laravel) and [Supabase](https://warmerly.com/transactional-email/integrations/supabase). > These endpoints answer `503 service_unavailable` in an environment where transactional sending > is not configured. **Your transactional mail never shares an IP or account with cold outreach or warmup.** It sends through separate transactional infrastructure, isolated per workspace, so a campaign's reputation can never put your password resets in spam. For the same reason, send transactional mail from a domain (or subdomain, such as `mail.example.com`) you do not use for cold outreach. ## Authentication Transactional email has its own API keys, separate from the rest of the Warmerly API. Create one in the app under **Transactional email → API keys** and send it as a bearer token: ``` Authorization: Bearer wm_tx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` (`X-Api-Key: wm_tx_…` works too.) A key belongs to one workspace and acts only on it. It works only on `/transactional/*` endpoints, and a general Warmerly API key (`wmv_…`) is refused here. | Permission | Can | | --- | --- | | **Sending** | Send email only. Can be limited to one sending domain. Use this in your application. | | **Full access** | Send, list and read emails, add and verify domains. | A key is shown once, when you create it. Revoking it takes effect on the next request. ## Add a sending domain ``` POST /transactional/domains ``` | Field | Type | Required | Description | | --- | --- | --- | --- | | `domain` | string | Yes | The domain you will send **from**, e.g. `mail.example.com`. | The response lists the DNS records to publish at your DNS provider: three CNAMEs for Easy DKIM, an MX and an SPF TXT on a `bounce.` subdomain for the custom MAIL FROM address, and a DMARC policy. There is **no root-level record**: your domain's own SPF and MX are untouched, and it keeps receiving mail exactly where it does today. The only MX is on `bounce.`, where bounce and complaint reports are received. The DKIM keys are 2048-bit, and they are rotated for you without any change to these records. ```bash curl -X POST https://app.warmerly.com/api/v1/transactional/domains \ -H "Authorization: Bearer wm_tx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "domain": "mail.example.com" }' ``` `201 Created`: ```json { "domain": { "id": "4f2c…", "domain": "mail.example.com", "status": "pending", "records": [ { "type": "CNAME", "name": "abc123._domainkey", "content": "abc123.dkim.amazonses.com", "required": true }, { "type": "CNAME", "name": "def456._domainkey", "content": "def456.dkim.amazonses.com", "required": true }, { "type": "CNAME", "name": "ghi789._domainkey", "content": "ghi789.dkim.amazonses.com", "required": true }, { "type": "MX", "name": "bounce", "content": "feedback-smtp.eu-north-1.amazonses.com", "priority": 10, "required": true }, { "type": "TXT", "name": "bounce", "content": "v=spf1 include:amazonses.com ~all", "required": true }, { "type": "TXT", "name": "_dmarc", "content": "v=DMARC1; p=none", "required": true } ], "lastVerifiedAt": null, "createdAt": "2026-09-23T21:00:00.000Z" } } ``` | Error | When | | --- | --- | | `400 bad_request` | Not a valid domain. | | `409 conflict` | The domain is already in use elsewhere in Warmerly (for example as a OneMail domain, or by another workspace). | | `503 service_unavailable` | Transactional sending is not enabled for your workspace yet. | ## List sending domains ``` GET /transactional/domains ``` ```bash curl https://app.warmerly.com/api/v1/transactional/domains \ -H "Authorization: Bearer wm_tx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` `200 OK`: `{ "domains": [ … ] }`, each in the shape shown above. ## Verify a sending domain ``` POST /transactional/domains/{id}/verify ``` Checks the records: the sending service confirms the three DKIM CNAMEs and the `bounce.` MX and SPF (the custom MAIL FROM), and Warmerly looks the DMARC record up in public DNS. Once all of them pass, `status` becomes `verified` and you can send from any address on the domain. A verified domain stays verified if a later check fails. DNS changes can take a few minutes to propagate, so it is safe to call this again. It is limited to 30 checks every 10 minutes. ```bash curl -X POST https://app.warmerly.com/api/v1/transactional/domains/4f2c…/verify \ -H "Authorization: Bearer wm_tx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` `200 OK`: `{ "domain": { …, "status": "verified" }, "missing": [], "advisories": [] }`. While records are still missing, `status` stays `pending` and `missing` lists them. `advisories` is advice that never blocks verification, each `{ "code", "message" }`: | Code | Meaning | | --- | --- | | `no_mx` | Neither the domain nor its parent domain has an MX record, so it cannot receive email. See [Deliverability](#deliverability). | | `dmarc_no_reports` | DMARC is `p=none` with no `rua=` address, so nobody receives reports about mail sent as the domain. | The response also carries `health`, the domain's full health checklist (below), checked at the same time. It never decides verification. ## Check a domain's health ``` GET /transactional/domains/{id}/health POST /transactional/domains/{id}/health ``` A checklist of everything that affects how inboxes treat mail from the domain: the three DKIM CNAMEs, the `bounce.` MX and SPF, DMARC and how strong its policy is, the domain and its `bounce.` subdomain against public blocklists, and, as advice about the domain in general, its own SPF, whether it can receive mail (MX), and MTA-STS / TLS reporting. `GET` returns the last result (up to 15 minutes old) and checks afresh when there isn't one; `POST` checks now, at most 3 times every 10 minutes per domain (`429` after that). `GET` needs any key that can read; `POST` a full-access key. ```bash curl https://app.warmerly.com/api/v1/transactional/domains/4f2c…/health \ -H "Authorization: Bearer wm_tx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` `200 OK`: ```json { "health": { "domain": "mail.acme.com", "checkedAt": "2026-09-28T10:00:00.000Z", "overall": "warn", "score": 93, "unknownCount": 0, "checks": [ { "id": "dkim", "label": "DKIM signing", "state": "pass", "advisory": false, "summary": "All 3 DKIM records are published and correct." }, { "id": "dmarc", "label": "DMARC policy", "state": "warn", "advisory": false, "summary": "DMARC is published with p=none (monitor only), but …", "fix": "Once your reports show only your own senders passing, …" } ] }, "cached": true } ``` Each check's `state` is `pass`, `warn`, `fail` or `unknown`. `unknown` means the lookup couldn't run (a DNS timeout, a blocklist that didn't answer), and is never counted as a pass. Advisory checks (`advisory: true`) are never `fail`. `overall` is `fail` if any check fails, `unknown` if a required check couldn't run, `warn` if anything could be better, else `pass`. `score` (0-100) is weighted over the checks that ran, and stays below 50 while a required check fails. Check ids: `dkim`, `mail_from`, `dmarc`, `blocklist_domain`, `blocklist_bounce`, `root_spf`, `root_mx`, `mta_sts`. ## Remove a sending domain ``` DELETE /transactional/domains/{id} ``` You can no longer send from the domain. Its email log and any API key limited to it are deleted with it. Needs a full-access key. `200 OK`: `{ "removed": true }`. ## Send an email ``` POST /transactional/emails ``` | Field | Type | Required | Description | | --- | --- | --- | --- | | `from` | string | Yes | `"Acme "` or a bare address. Must be on a **verified** sending domain. | | `to` | string or string[] | Yes | Recipients, up to the limit for your plan (see "Sending limits" below). | | `cc`, `bcc` | string or string[] | No | Counted with `to`. | | `reply_to` | string | No | | | `subject` | string | Yes | | | `html`, `text` | string | One of them | Send both for the best inbox placement. | | `headers` | object | No | Extra headers, e.g. `List-Unsubscribe`. | | `tags` | object | No | Your own key/value labels, returned in the email log. | Send an `Idempotency-Key` header to make retries safe: repeating a request with the same key returns the first email (`"duplicate": true`) instead of sending a second one. If the email is throttled or the mail server can't be reached, and nothing was handed over, the email is **queued** rather than dropped: the request still answers `202` with `"status": "queued"`, and Warmerly retries it after 1, 5, 15 and 60 minutes, then hourly, for up to 24 hours. It moves to `sent` when an attempt is accepted, or to `failed` after 24 hours. You don't need to retry it yourself; a repeat with the same `Idempotency-Key` answers `"status": "queued", "duplicate": true` and sends nothing extra. Each attempt appears in the email's events as `retrying`. If a request fails with `502 send_failed`, its `details` say whether a retry with the same key will send: - `"interrupted": false`: the email was refused for delivery and it was not sent. A request answers this way only when queueing it wasn't possible; an email that ends `failed` after 24 hours of retries reads the same way. Retrying with the **same** key tries again, under the same email id. - `"interrupted": true`: the send was cut off before delivery was confirmed (for example a restart, a timeout or a dropped connection mid-send), so it **may have been delivered**. It is never retried automatically. Retrying with the same key does not send it again and answers the same `send_failed`. If you would rather risk a duplicate than a missing email, retry with a new key. `details.lastResponse` is the mail server's answer, or what happened instead. Recipients on your workspace's [suppression list](https://docs.warmerly.com/suppression) (hard bounces, spam complaints, unsubscribes, addresses you added) are skipped. If every recipient is suppressed, the email is recorded with status `suppressed` and nothing is sent. A hard bounce or a spam complaint adds the address to the list automatically. ```bash curl -X POST https://app.warmerly.com/api/v1/transactional/emails \ -H "Authorization: Bearer wm_tx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Idempotency-Key: reset-7f3a9c" \ -H "Content-Type: application/json" \ -d '{ "from": "Acme ", "to": "jane@example.org", "subject": "Reset your password", "html": "

Click here to reset your password.

", "text": "Reset your password: https://example.com/reset/…" }' ``` `202 Accepted`: ```json { "id": "9b1e…", "status": "sent", "duplicate": false } ``` `sent` means the email was accepted for delivery. Delivery to the recipient's server is reported afterwards, in the email's events. `queued` means it could not be handed over just now and it will be retried for up to 24 hours (see above). | Error | When | | --- | --- | | `400 bad_request` | Invalid body, or the From domain is not a verified sending domain. | | `403 forbidden` | The key is limited to a different sending domain. | | `403 sending_paused` | Sending is paused for this workspace, because of its bounce or complaint rate or while we review its activity. Contact support. Do not retry. | | `422 content_rejected` | The message was refused by our abuse screening (for example phishing-style or spam wording). Do not retry it unchanged; if you believe it is a mistake, contact support. | | `429 rate_limited` | The workspace reached its hourly or daily sending limit (below). Try again later, or move to a paid plan for a higher limit. | | `429 quota_exceeded` | The plan's monthly allowance, plus the free buffer, is used up. | | `429 too_many_requests` | More than 600 sends a minute from one workspace. | | `502 send_failed` | The email could not be sent or queued, or the send was interrupted (see `details.interrupted`; `details.id` is its log entry). | | `503 service_unavailable` | Transactional sending is not enabled for your workspace yet. | ### Sending limits To keep the service clean for everyone, how much a workspace can send in an hour and a day, and to how many recipients per email, depends on the plan and how long the workspace has existed. A `429 rate_limited` or a `400` about the recipient limit tells you when you hit one. | Workspace | Recipients per email | Per hour | Per day | | --- | --- | --- | --- | | Free, first 7 days | 5 | 50 | 200 | | Free, after that | 20 | 300 | 2,000 | | Any paid plan | 50 | 5,000 | 50,000 | This API is for one-to-one messages your app triggers: sign-in codes, password resets, receipts and alerts. Newsletters, marketing and bulk mail are not allowed, and a workspace that sends them, or whose mail is reported as spam or bounces heavily, is paused automatically and may be suspended. ## List emails ``` GET /transactional/emails ``` The 50 most recent emails, newest first. Needs a full-access key. Optional query parameters: | Parameter | Meaning | | --- | --- | | `before` | The `createdAt` of the last email you have, for the next page. | | `status` | Only this status, for example `bounced`. | | `q` | Recipient or subject contains this text (case-insensitive). | | `domainId` | Only emails from this sending domain (`400` if it isn't one of yours). | | `days` | Only the last `7`, `30` or `90` days. | | `limit` | Page size, 1 to 50. | ```bash curl "https://app.warmerly.com/api/v1/transactional/emails?q=jane%40example.org&days=30" \ -H "Authorization: Bearer wm_tx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` `200 OK`: `{ "emails": [ { "id", "from", "to", "subject", "status", "tags", "createdAt", "sentAt", "domainId", "domain" } ] }`. ## Get sending metrics ``` GET /transactional/metrics ``` Totals, a daily series and breakdowns for the last `days` (`7`, `30` or `90`; default `30`) UTC days, today included. Pass `domainId` for one sending domain. Needs a full-access key. ```bash curl "https://app.warmerly.com/api/v1/transactional/metrics?days=30" \ -H "Authorization: Bearer wm_tx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` `200 OK`: ```json { "days": 30, "domainId": null, "start": "2026-08-28", "previousStart": "2026-07-29", "kpis": { "sent": { "current": 1200, "previous": 1000, "change": 20 }, "deliveredRate": { "current": 0.991, "previous": 0.988, "change": 0.3 }, "bounceRate": { "current": 0.009, "previous": 0.012, "change": -0.3 }, "complaintRate": { "current": 0.0004, "previous": null, "change": null }, "suppressed": { "current": 3, "previous": 1, "change": 200 }, "failed": { "current": 0, "previous": 0, "change": 0 } }, "measured": { "current": 1180, "previous": 990 }, "daily": [ { "day": "2026-08-28", "total": 40, "sent": 40, "delivered": 39, "bounced": 1, "complained": 0, "inFlight": 0, "failed": 0, "suppressed": 0, "deliveredRate": 0.975, "bounceRate": 0.025, "complaintRate": 0 } ], "byDomain": [ { "domainId": "4f2c…", "domain": "mail.acme.com", "sent": 1200, "delivered": 1170, "bounced": 11, "complained": 1, "deliveredRate": 0.991 } ], "byProvider": [ { "provider": "Gmail", "sent": 700, "delivered": 695, "bounced": 4, "complained": 1, "deliveredRate": 0.994 } ], "topRecipientDomains": [ { "domain": "gmail.com", "provider": "Gmail", "sent": 690, "delivered": 686, "bounced": 3, "complained": 1, "deliveredRate": 0.994 } ] } ``` - Rates are 0 to 1, over emails with a known outcome (delivered, bounced or marked as spam). A period rate is `null` until 20 emails have one. - `change` compares with the previous period of the same length: percent for counts (`null` when the previous period had none), percentage points for rates. - `sent` counts emails accepted for delivery. `total` (daily) counts every email created. - `byProvider` and `topRecipientDomains` count per `to` recipient, not per email. Providers are Gmail, Outlook, Yahoo, iCloud and Other. - `400` if `days` isn't 7, 30 or 90, or `domainId` isn't one of your sending domains. ## Get an email and its delivery timeline ``` GET /transactional/emails/{id} ``` ```bash curl https://app.warmerly.com/api/v1/transactional/emails/9b1e… \ -H "Authorization: Bearer wm_tx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` `200 OK`: ```json { "email": { "id": "9b1e…", "status": "delivered", "subject": "Reset your password", "html": "

…

", "text": "…", "replyTo": null, "bodyClearedAt": null, "…": "…" }, "events": [ { "type": "accepted", "recipient": null, "detail": "010f0192…-000000", "createdAt": "…" }, { "type": "delivered", "recipient": "jane@example.org", "detail": null, "createdAt": "…" } ] } ``` `html` and `text` are the content as sent. They are kept for 30 days, then set to `null` and `bodyClearedAt` records when; the rest of the email and its events are kept. ### Statuses | Status | Meaning | | --- | --- | | `queued` | Waiting to be sent: retried with backoff for up to 24 hours. | | `sent` | Accepted for delivery, delivery in progress. | | `delivered` | The recipient's mail server accepted it. | | `deferred` | A temporary failure; delivery is being retried. | | `bounced` | Permanently rejected. The address has been suppressed. | | `complained` | The recipient marked it as spam. The address has been suppressed. | | `failed` | Not sent: refused for delivery, still refused after 24 hours of retries, or interrupted mid-send (it may have gone out; see `send_failed`). | | `suppressed` | Every recipient was on the suppression list; nothing was sent. | ## Deliverability Verification proves the mail is yours. Whether it lands in the inbox also depends on how much inbox providers trust the domain. Three things help most: - **Send from a domain that can receive email.** Gmail and Outlook distrust mail from a domain with no MX record: nobody can reply to it, which is typical of throwaway spam domains. Use a domain that already receives mail, or a subdomain of one (`mail.example.com` is fine when `example.com` has an MX). Verify reports this as the `no_mx` advisory. - **Expect new domains to warm up.** A domain with no sending history starts with no reputation. Mail your users asked for (sign-in links, receipts) builds it fastest. Start with that traffic and grow volume over a few weeks, rather than sending everything on day one. - **Read your DMARC reports.** The `p=none` record we suggest only monitors. Add `rua=mailto:dmarc@example.com` to receive reports, then move to `p=quarantine` once everything you send passes SPF and DKIM. Plain, expected content helps too: send HTML and a plain-text part together, use a subject that says what the email is, and avoid one-line test messages to people who never asked for them. --- # Suppression The suppression list is the set of email addresses that must never be sent to: unsubscribes, bounces, and addresses added by hand. It is enforced automatically across campaigns and the [lead export/push endpoints](https://docs.warmerly.com/leads): a suppressed address is skipped, not queued. In the dashboard the list is called **Do not contact**. ## What gets suppressed automatically You rarely need to add anything yourself. Warmerly adds an address to the list when: | Event | Reason recorded | Scope | | --- | --- | --- | | A lead uses the unsubscribe link or the one-click unsubscribe header in a campaign email | `unsubscribed` | Your workspace | | A lead replies with an unmistakable unsubscribe request (the opt-out path for mailboxes that send without our link) | `unsubscribed` | Your workspace | | A campaign email hard-bounces, or the receiving server refuses it as an address that does not exist | `bounced` | All Warmerly workspaces | | A recipient files a spam complaint that Warmerly can verify | `complained` | Your workspace and all workspaces | | A transactional email hard-bounces or draws a complaint, or the same address soft-bounces twice in a row | `bounced` or `complained` | Your workspace | | You or a teammate add it by hand, through the dashboard, the API or an AI assistant | `manual` | Your workspace | A dead mailbox is suppressed for every workspace, because no one can reach it. That platform-wide list is not visible to customers. When one of your leads matches it, the lead is shown as **Unavailable mailbox**, which does not reveal who else mailed the address. A refusal that is about your message or sending reputation (a spam-filter or blocklist rejection) is not treated as a dead address and does not suppress anyone. A reply such as "not interested" stops that lead's sequence but does not put them on the list. See [What stops a campaign sequence for a lead?](https://docs.warmerly.com/help/what-stops-a-sequence). ## How suppression works with campaigns Suppression is **workspace-wide**, not per campaign or per project. An opt-out holds across every campaign and every mailbox in the workspace, including campaigns you create later. Warmerly checks the recipient right before each email is sent, so an address added a second ago is already honored. A suppressed lead is not sent to: its status becomes **Unsubscribed** or **Unavailable mailbox** depending on why the address is listed, and its sequence stops. Importing the same address again into another campaign does not bypass the list. Verification is separate. [Email verification](https://docs.warmerly.com/verify) checks whether an address can receive mail, and does not read or change the suppression list. Verify lists before you import them to keep bounces low, and rely on the list to honor opt-outs. ## The list is write-only **`POST /suppression` is the only customer-callable endpoint on this resource.** Adding an address works with your API key and in the dashboard at **Settings > Do not contact**. Listing, exporting and removing are staff-only and return `404 not_found` for a customer key, including an Agency one. That split is deliberate. The list aggregates bounce evidence across every tenant, so enumerating or exporting it would expose which addresses other customers have been mailing. Adding stays open because it has to: someone who says "stop emailing me" on a call must be suppressible immediately, not after a support ticket. If you need an address taken **off** the list, [contact support](https://warmerly.com/contact) since removal means campaigns may mail that person again, so it stays with operators and stays audit-logged. `404` here means "not available to you", not "no suppression list exists". It is deliberately indistinguishable from a missing route. ## Add addresses ``` POST /suppression ``` Requires `X-Api-Key`. **Not** project-scoped. The list applies to your whole active workspace (the same one the dashboard has selected), not a single project. Send [`X-Workspace-Id`](https://docs.warmerly.com/authentication#required-headers) to choose the workspace explicitly. | Field | Type | Required | Description | | --- | --- | --- | --- | | `emails` | string (1-1,000,000 chars) | Yes | A blob of addresses separated by commas, semicolons, tabs, or newlines. Tolerates `Name ` formatting and a leading `email`/`email_address` CSV header, so you can paste a raw CSV column unedited. | Up to **5,000** addresses per request. Every address added this way is recorded with `reason: "manual"`; the `unsubscribed` and `bounced` reasons are set only by Warmerly itself (the unsubscribe link and the bounce classifier), so a hand-typed address is never attributed to either. ```bash curl -X POST https://app.warmerly.com/api/v1/suppression \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "emails": "jane@example.com, john@example.com" }' ``` `201 Created`: ```json { "added": 2, "alreadyPresent": 0, "invalid": [] } ``` `added` is new rows inserted; `alreadyPresent` is addresses already on the list (adding one twice is a no-op); `invalid` lists tokens that looked like an email attempt (contained `@`) but failed validation. Errors: | Status | `message` | When | | --- | --- | --- | | `400` | `invalid_body` | `emails` missing, empty, or over 1,000,000 characters. | | `400` | `no_valid_emails` | Nothing in `emails` parsed as a valid address. `details.invalid` samples up to 20 of the rejected tokens. | | `400` | `too_many_emails` | More than 5,000 addresses parsed. `details` carries `{ max, received }`. | Every add is recorded in the workspace audit log as `suppression.added` (removals, when staff perform them, as `suppression.removed`). ## Other ways to add addresses - **Dashboard.** Open **Settings > Do not contact**, paste addresses into **Email addresses** (one per line, or separated by commas; a pasted CSV column works) and click **Add to do-not-contact**. A toast reports how many were added, how many were already suppressed and how many were skipped as invalid. - **AI assistants.** The `suppress_emails` tool on the [MCP server](https://docs.warmerly.com/ai) adds up to 500 addresses per call to the connected workspace, as `manual`. It stays available while a workspace is billing-locked, because it only ever stops mail. - **Bulk import.** There is no separate import endpoint. For a large list, split it into batches of up to 5,000 addresses and call `POST /suppression` once per batch. Re-sending a batch is safe because duplicates are counted as `alreadyPresent`. ## Common questions **Can I export the list or see which addresses are on it?** No. The list is not visible to customers, by design. Keep your own record of the addresses you add if you need one. **Can I remove an address I added by mistake?** Not yourself. The dashboard says suppressions are permanent so an opt-out can never be reversed by accident. [Contact support](https://warmerly.com/contact) and the request is reviewed. **Does suppressing an address stop mail already in flight?** Mail that has already been sent cannot be recalled. Anything not yet sent is checked against the list at send time and skipped. **Does the list apply to other workspaces I own?** No. Each workspace has its own list, so add the address in every workspace that might email them. Bounced mailboxes are the exception, since those are suppressed across the platform. **Is it case sensitive?** No. Addresses are trimmed and lowercased before they are stored and checked. **Do transactional emails respect it?** Yes. A transactional recipient on the list is dropped, and if every recipient is suppressed the email is recorded as `suppressed` and nothing is sent. See [Transactional email](https://docs.warmerly.com/transactional). ## Related - [Leads](https://docs.warmerly.com/leads): export and push-to-campaign both filter against this list - [Campaigns](https://docs.warmerly.com/campaigns): suppressed leads are skipped at send time - [Unsubscribe links](https://docs.warmerly.com/help/unsubscribe-links): what recipients see and what happens when they click - [Troubleshooting](https://docs.warmerly.com/troubleshooting): "my campaign is not sending" includes the suppression case --- # Webhooks Subscribe a URL you control to receive HTTP `POST` notifications for mailbox health events, health score drops, auto-pauses, OAuth disconnects, DNS changes, and similar. This page covers managing **outbound webhook subscriptions**; it's unrelated to Warmerly's own inbound provider webhooks (Stripe, Unipile), which aren't part of the public API. **Webhook subscriptions are an Agency-plan feature.** Listing, creating, and re-enabling a subscription return `403 agency_plan_required` on Starter and Growth workspaces. Deleting a subscription you already hold is always allowed, even after a downgrade. All endpoints below require `X-Api-Key` and are not project-scoped, a subscription receives events for every account you own across every project. ## Event types Pass one or more of these in `eventTypes` when creating a subscription: | Event type | Description | | --- | --- | | `score_drop` | A mailbox's warmup health score dropped. | | `score_floor` | A mailbox's health score hit a critical floor. | | `oauth_disconnected` | A sign-in connected mailbox (Microsoft 365, Outlook, or Gmail connected before 2026-09-15) lost its connection. | | `auth_fail` | A mailbox failed to authenticate. | | `dns_changed` | A mailbox's DNS records (SPF/DKIM/DMARC) changed. | | `smtp_fail` | An SMTP send failed for a mailbox. | | `imap_fail` | An IMAP sync failed for a mailbox. | | `flagged` | A mailbox was flagged. | | `auto_paused` | A mailbox was automatically paused. | | `auto_resumed` | A mailbox was automatically resumed after a pause. | | `manual_pause` | A mailbox was manually paused from the dashboard. | | `aged_in` | A mailbox finished warmup ramp-up and is now fully aged in. | | `marked_dead` | A mailbox was marked dead. | | `oauth_refresh_fail` | An OAuth token refresh failed for a mailbox. | | `oauth_connected` | A mailbox was connected via OAuth. | | `oauth_reconnected` | A previously disconnected OAuth mailbox was reconnected. | ## List subscriptions ``` GET /webhooks/subscriptions ``` Returns your active (non-revoked) subscriptions. The secret is masked to its last 4 characters, it's only shown in full at creation time. ```bash curl https://app.warmerly.com/api/v1/webhooks/subscriptions \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "subscriptions": [ { "id": "e5b3a7c2-8d4e-4f0a-9c2b-6a1d3e8f5c7b", "name": "Mailbox alerts → Slack relay", "targetUrl": "https://example.com/hooks/warmerly", "secret": "••••7c9e", "eventTypes": ["score_drop", "oauth_disconnected"], "active": true, "lastDispatchedAt": "2026-08-18T09:00:00.000Z", "lastDeliveryStatus": "success", "lastDeliveryError": null, "consecutiveFailures": 0, "createdAt": "2026-07-01T10:00:00.000Z" } ] } ``` ## Create a subscription ``` POST /webhooks/subscriptions ``` | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string (1-120 chars) | Yes | A label to identify the subscription. | | `targetUrl` | string (URL) | Yes | Must be a public `https://` URL, localhost, private/link-local IP ranges, and non-https URLs are rejected. | | `eventTypes` | string[] | Yes | One or more values from [Event types](#event-types). | Each user can hold at most **10 active subscriptions**; creating an 11th returns `400 too_many_subscriptions`. ```bash curl -X POST https://app.warmerly.com/api/v1/webhooks/subscriptions \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "name": "Mailbox alerts", "targetUrl": "https://example.com/hooks/warmerly", "eventTypes": ["score_drop", "auto_paused", "oauth_disconnected"] }' ``` `201 Created`: ```json { "subscription": { "id": "e5b3a7c2-8d4e-4f0a-9c2b-6a1d3e8f5c7b", "name": "Mailbox alerts", "targetUrl": "https://example.com/hooks/warmerly", "eventTypes": ["score_drop", "auto_paused", "oauth_disconnected"] }, "secret": "8f2a7c9e4b1d6f3a9c2e5b8d1a4f7c9e6b3d8a1f4c7e9b2d5a8f1c4e7b9d3a6f" } ``` **`secret` is only ever returned in full here.** Store it — it's used to verify the `X-Warmerly-Signature` header on every delivery (see [Verifying deliveries](#verifying-deliveries) below). It cannot be retrieved again; delete the subscription and create a new one if you lose it. Errors: `400 bad_request` (`invalid_body` for a malformed request, or `unknown_event_types` with `details: { unknown: [...] }` if `eventTypes` contains a value not in the table above), `403 agency_plan_required` if your plan doesn't include webhooks. ## Update a subscription ``` PATCH /webhooks/subscriptions/{id} ``` | Field | Type | Required | Description | | --- | --- | --- | --- | | `active` | boolean | Yes | Enable or disable delivery. Re-enabling also resets `consecutiveFailures` to 0. | Currently the only supported update is toggling `active`, there's no way to change `targetUrl` or `eventTypes` in place; delete and recreate the subscription instead. This endpoint is also how you manually re-enable a subscription the delivery sweep auto-disabled (see [Delivery & retries](#delivery--retries)). ```bash curl -X PATCH https://app.warmerly.com/api/v1/webhooks/subscriptions/e5b3a7c2-8d4e-4f0a-9c2b-6a1d3e8f5c7b \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "active": true }' ``` ```json { "subscription": { "id": "e5b3a7c2-8d4e-4f0a-9c2b-6a1d3e8f5c7b", "name": "Mailbox alerts", "targetUrl": "https://example.com/hooks/warmerly", "eventTypes": ["score_drop", "auto_paused", "oauth_disconnected"], "active": true } } ``` `404 not_found` if the subscription doesn't exist or isn't yours. ## Delete a subscription ``` DELETE /webhooks/subscriptions/{id} ``` Revokes (soft-deletes) the subscription; deliveries stop immediately. Not gated on plan tier, a downgraded workspace can still turn off deliveries it can no longer manage. ```bash curl -X DELETE https://app.warmerly.com/api/v1/webhooks/subscriptions/e5b3a7c2-8d4e-4f0a-9c2b-6a1d3e8f5c7b \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "revoked": true } ``` `404 not_found` if the subscription doesn't exist, isn't yours, or was already revoked. ## Delivery & retries Deliveries are dispatched by a background sweep (not real-time) that polls for new events roughly every few minutes. Each delivery is a `POST` to your `targetUrl`: ```json { "id": "9d1e0b7a-5e7b-4f10-b2aa-1c8f0d3e6a4b", "type": "score_drop", "accountId": "3a6f9e2e-4b7a-4e9a-9b1d-6e3a2f8c1a10", "occurredAt": "2026-08-18T09:00:00.000Z", "data": { "severity": "warning", "title": "Health score dropped", "scoreBefore": 88, "scoreAfter": 61 } } ``` `data`'s shape varies by `type`, it mirrors the underlying alert/account event and isn't separately typed per event today (documenting the exact `data` shape for every event type is a known gap; see [Known gaps](#known-gaps-in-this-page)). - A delivery is retried up to **3 times** with exponential backoff if your endpoint doesn't respond `2xx` within **5 seconds**, or errors/times out. - A subscription is **automatically disabled** (`active: false`) after **10 consecutive failed sweeps**. Re-enable it with `PATCH .../{id}`. - Up to 50 events per subscription are delivered per sweep; if you have a burst larger than that, the remainder is delivered on the next sweep. - Redirects are not followed automatically (`redirect: "manual"`), respond `2xx` directly from `targetUrl`. ### Verifying deliveries Every delivery carries an `X-Warmerly-Signature` header: the hex-encoded HMAC-SHA256 of the raw request body, signed with your subscription's `secret`. ``` X-Warmerly-Signature: 3f9a7c2e... (hex-encoded HMAC-SHA256 of the raw body) ``` Verify it by recomputing the HMAC over the exact bytes of the received body and comparing: ```js const crypto = require("crypto"); const expected = crypto.createHmac("sha256", subscriptionSecret).update(rawBody).digest("hex"); const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(receivedSignature)); ``` ## Known gaps in this page - The exact `data` payload shape is not separately documented per event type, it passes through the underlying alert/account event record as-is, and cataloguing all 16 shapes precisely was out of scope for this pass. - There's no endpoint to list recent delivery attempts/history beyond the single `lastDispatchedAt`/`lastDeliveryStatus`/`lastDeliveryError` snapshot on the subscription itself. --- # Workspaces & Projects Every account belongs to one or more **workspaces**: the top-level tenant that owns billing, members, and branding. Each workspace contains one or more **projects**, and mailboxes, campaigns, and inbox data all attach to a project (selected via the `X-Project-Id` header on other endpoints, see [Authentication](https://docs.warmerly.com/authentication)). Workspace and project management endpoints below identify the workspace/project by ID in the URL path, so they generally do **not** require `X-Project-Id`. The one exception is listing/creating projects, which operates on your *active* workspace (see [Projects](#projects) below). ## Roles Workspace members have one of three roles: | Role | Can do | | --- | --- | | `owner` | Everything, including deleting the workspace and managing billing. Every workspace has exactly one owner. | | `admin` | Rename the workspace, manage members/invites and branding. Cannot delete the workspace, manage billing, or modify/remove the owner. | | `member` | Read the workspace and use its projects. Cannot manage members, rename, or delete. | Granting the `owner` role to another member **transfers ownership**: the caller must already be the owner, and their own role is downgraded to `admin`. ## Workspaces ### List your workspaces ``` GET /workspaces ``` Returns every workspace you're a member of. ```json { "workspaces": [ { "id": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "name": "Acme Inc", "role": "owner", "status": "active", "logoUrl": "https://app.warmerly.com/api/images/...", "isOwner": true, "planName": "Agency", "billedThrough": null, "clientCount": 2, "deletionScheduledFor": null, "purgeAt": null } ] } ``` `status` is `"active"`, `"pending"` (an extra workspace waiting for its own plan) or `"deleted"` (in its 30-day recovery window). `billedThrough` is set on an Agency client workspace and names the Agency workspace whose plan it shares; `planName` is then `null`. `clientCount` is how many client workspaces share an Agency workspace's plan. ### Create a workspace ``` POST /workspaces ``` | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | Yes | 1-80 characters. | ```bash curl https://app.warmerly.com/api/v1/workspaces \ -X POST \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "name": "Acme Inc" }' ``` ```json { "workspace": { "id": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "name": "Acme Inc", "role": "owner", "status": "active", "logoUrl": null }, "billedThrough": { "id": "3c59dc04-8f37-4b8b-9c0e-7d3a1f1e2b4d", "name": "My Agency" } } ``` The caller becomes the workspace's `owner`. How it is paid for depends on your plan: - **On Agency**, it is a client workspace: `status` is `"active"` straight away, it shares your Agency plan's allowances, and `billedThrough` names the Agency workspace. - **Otherwise**, `status` is `"pending"` and `billedThrough` is `null` until a paid plan is chosen for it in the app. Free is not available for extra workspaces. If you already have a pending workspace, that one is returned (renamed to `name`) instead of creating a duplicate. ### Get a workspace ``` GET /workspaces/{id} ``` Returns the workspace, its members, and (if you're an `owner`/`admin`) its pending invites. ```json { "workspace": { "id": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "name": "Acme Inc", "logoUrl": null, "role": "owner", "ownerUserId": "3c2b1a09-..." }, "members": [ { "userId": "3c2b1a09-...", "email": "you@acme.com", "name": "Jordan", "image": null, "role": "owner", "createdAt": "2026-01-10T12:00:00.000Z" } ], "invites": [ { "id": "b2f9...", "email": "new.hire@acme.com", "role": "member", "status": "pending", "createdAt": "2026-06-01T09:00:00.000Z", "expiresAt": "2026-06-08T09:00:00.000Z" } ] } ``` `invites` is empty for members without `members:manage` permission (i.e. plain `member` role). ### Rename a workspace ``` PATCH /workspaces/{id} ``` Requires `owner` or `admin`. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | Yes | 1-80 characters. | ```bash curl https://app.warmerly.com/api/v1/workspaces/8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a \ -X PATCH \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "name": "Acme Incorporated" }' ``` ```json { "workspace": { "id": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "name": "Acme Incorporated" } } ``` ### Delete a workspace ``` DELETE /workspaces/{id} ``` Requires `owner`. What happens depends on the workspace, and `phase` says which: | `phase` | When | What happens | | --- | --- | --- | | `removed` | A pending workspace that was never paid for | Deleted immediately. | | `scheduled` | It has its own paid subscription | The subscription stops renewing; the workspace works until `effectiveAt`, then enters recovery. No refund. | | `retention` | Anything else (Free, or an Agency client) | Locked now and kept until `purgeAt` (30 days), then permanently deleted with everything under it. | ```json { "ok": true, "phase": "retention", "effectiveAt": "2026-09-23T10:00:00.000Z", "purgeAt": "2026-10-23T10:00:00.000Z", "nextWorkspaceId": "3c59dc04-8f37-4b8b-9c0e-7d3a1f1e2b4d" } ``` `nextWorkspaceId` is the workspace you were switched to, when the deleted one stopped being usable. ### Restore a workspace ``` POST /workspaces/{id}/restore ``` Requires `owner`. Undoes a deletion without a card: a `scheduled` deletion is called off and the subscription carries on, and a workspace in recovery comes back into its Agency plan, keeps its own subscription if it still has one, or otherwise returns on the Free plan. ```json { "outcome": "free" } ``` `outcome` is `deletion_cancelled`, `agency_pool`, `subscription_kept`, `free` or `not_deleted`. ## Members ### Change a member's role ``` PATCH /workspaces/{id}/members/{userId} ``` Requires `owner` or `admin`. | Field | Type | Required | Description | | --- | --- | --- | --- | | `role` | `"owner"` \| `"admin"` \| `"member"` | Yes | New role for the member. | ```bash curl https://app.warmerly.com/api/v1/workspaces/8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a/members/3c2b1a09-... \ -X PATCH \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "role": "admin" }' ``` ```json { "ok": true } ``` Notes: - Only an `owner` may set `role: "owner"`, doing so **transfers ownership**; the caller's own role becomes `admin`. - An `admin` cannot change an `owner`'s role (`403 forbidden`). ### Remove a member ``` DELETE /workspaces/{id}/members/{userId} ``` Requires `owner` or `admin` to remove another member. A member may remove *themselves* (leave the workspace) regardless of role, except the `owner` — the owner must transfer ownership or delete the workspace first (`400 bad_request`). An `owner` can never be removed by another member (`403 forbidden`). ```json { "ok": true } ``` ## Invites ### List pending invites ``` GET /workspaces/{id}/invites ``` Requires `owner` or `admin`. ```json { "invites": [ { "id": "b2f9...", "email": "new.hire@acme.com", "role": "member", "status": "pending", "createdAt": "2026-06-01T09:00:00.000Z", "expiresAt": "2026-06-08T09:00:00.000Z" } ] } ``` ### Invite a member ``` POST /workspaces/{id}/invites ``` Requires `owner` or `admin`. | Field | Type | Required | Description | | --- | --- | --- | --- | | `email` | string | Yes | Invitee's email address. | | `role` | `"admin"` \| `"member"` | Yes | Role granted on acceptance. You cannot invite someone directly as `owner`. | ```bash curl https://app.warmerly.com/api/v1/workspaces/8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a/invites \ -X POST \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "email": "new.hire@acme.com", "role": "member" }' ``` ```json { "invite": { "id": "b2f9...", "email": "new.hire@acme.com", "role": "member", "status": "pending", "createdAt": "2026-06-01T09:00:00.000Z", "expiresAt": "2026-06-08T09:00:00.000Z" } } ``` `201 Created` on success. If the email already belongs to a member, returns `409 conflict`. A new invite replaces any existing pending invite for the same email. Invites expire after 7 days. If transactional email is configured, an invite email is sent automatically. ## Projects A project hangs off a workspace and is what campaigns, mailboxes, and inbox data attach to via `X-Project-Id`. Each workspace has exactly one project. Unlike the workspace/member endpoints above, listing and creating projects operates on your **active workspace** (the workspace currently selected in the dashboard/session) rather than a workspace ID in the URL or header. ### List projects ``` GET /projects ``` ```json { "projects": [ { "id": "2b6e1c3d-...", "name": "Default", "slug": "default", "description": null, "color": null, "icon": null, "createdAt": "2026-01-10T12:00:00.000Z", "campaignCount": 3, "accountCount": 5 } ] } ``` If your active workspace has no projects yet, a default one is created automatically before the list is returned, so this endpoint never returns an empty array. ### Create a project ``` POST /projects ``` | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | Yes | Project name. | | `slug` | string | Yes | Lowercase letters, numbers, and hyphens only (`^[a-z0-9-]+$`). A random suffix is appended automatically if the slug is already taken. | | `description` | string | No | Up to 2000 characters. | | `color` | string | No | Up to 32 characters. | | `icon` | string | No | Up to 64 characters. | | `defaultTimezone` | string | No | Up to 64 characters. | ```bash curl https://app.warmerly.com/api/v1/projects \ -X POST \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "name": "Q3 Outbound", "slug": "q3-outbound" }' ``` ```json { "project": { "id": "9d4f2a11-...", "name": "Q3 Outbound", "slug": "q3-outbound", "workspaceId": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "description": null, "color": null, "icon": null, "defaultTimezone": null, "createdAt": "2026-07-01T09:00:00.000Z" } } ``` `201 Created` on success. Returns `409 conflict` if the active workspace already has a project, a workspace can only ever have one. ### Get a project ``` GET /projects/{id} ``` Returns the project. Requires membership in the project's workspace. ```json { "project": { "id": "9d4f2a11-...", "name": "Q3 Outbound", "slug": "q3-outbound", "workspaceId": "8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a", "description": null, "color": null, "icon": null, "defaultTimezone": null, "createdAt": "2026-07-01T09:00:00.000Z" } } ``` ### Project stats ``` GET /projects/{id}/stats ``` A rollup for one project: what the dashboard's project switcher shows. ```json { "project": { "id": "…", "name": "SaaS Outreach", "slug": "saas-outreach-05adc35c", "workspaceId": "…", "userId": "…" }, "campaigns": { "total": 3, "active": 2 }, "accounts": { "total": 12 }, "leads": { "total": 145 }, "emails": { "sent": 300, "replied": 17, "replyRate": 5.7 } } ``` `replyRate` is a percentage of real campaign sends, not a warmup figure (see [How warmup works](https://docs.warmerly.com/how-warmup-works) for why the two must not be mixed). ## Workspace housekeeping ``` POST /workspaces/{id}/activate POST /workspaces/{id}/logo DELETE /workspaces/{id}/logo DELETE /workspaces/{id}/invites/{inviteId} ``` `activate` switches which workspace is "current" for session-based (dashboard) use and returns `{ "ok": true }`. **API-key callers rarely need it:** pass `X-Workspace-Id` on the request instead, which scopes that one call without changing any stored state. `logo` takes a `multipart/form-data` upload and returns `{ "logoUrl": "…" }`; `DELETE` removes it. `DELETE /workspaces/{id}/invites/{inviteId}` revokes a pending invite that has not been accepted. ## Errors In addition to the standard [error envelope](https://docs.warmerly.com/#conventions), these endpoints return: - `403 forbidden`: you're a member of the workspace/project but lack the required role for the action (e.g. a `member` trying to invite someone, or an `admin` trying to remove an `owner`). - `404 not_found`: the workspace or project doesn't exist, or you're not a member of it (workspace/project membership checks return `404`, not `403`, to avoid leaking existence to non-members). - `409 conflict`: inviting an email that's already a member. - `400 bad_request`: invalid body (e.g. bad slug format), or an owner trying to leave their own workspace without transferring ownership first. --- # API Keys Manage the API keys used to authenticate requests to the Warmerly API. This page covers creating, listing, and revoking keys programmatically. If you're looking for how to use a key you already have, see [Authentication](https://docs.warmerly.com/authentication). Key management endpoints are not project-scoped: they only need `X-Api-Key`, not `X-Project-Id`. **API access is an Agency-plan feature.** Listing and creating keys returns `403 agency_plan_required` on Starter and Growth workspaces; upgrade at [warmerly.com/pricing](https://warmerly.com/pricing). Revoking a key you already hold is always allowed, even after a downgrade. ## List keys ``` GET /keys ``` Returns all of your active (non-revoked) keys, newest first. The raw secret is never returned, only the id, name, prefix, rate limit, and usage metadata. ```bash curl https://app.warmerly.com/api/v1/keys \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "keys": [ { "id": "3b1f6e2a-9c4d-4e2a-8b5f-6a2c1d9e0f7b", "name": "CI pipeline", "prefix": "wmv_7f3a2c", "rateLimitPerMin": 60, "lastUsedAt": "2026-07-01T09:12:44.000Z", "createdAt": "2026-06-20T14:03:11.000Z" }, { "id": "9a2d4c11-5e7b-4f10-b2aa-1c8f0d3e6a4b", "name": "Zapier", "prefix": "wmv_9d1e0b", "rateLimitPerMin": 120, "lastUsedAt": null, "createdAt": "2026-06-18T08:47:02.000Z" } ] } ``` | Field | Type | Description | | --- | --- | --- | | `id` | string (UUID) | Key ID, use this to revoke the key. | | `name` | string | The label you gave the key when creating it. | | `prefix` | string | The first few characters of the key (`wmv_...`), useful for identifying which key is which without exposing the secret. | | `rateLimitPerMin` | number | Requests per minute allowed for this key. | | `lastUsedAt` | string \| null | ISO 8601 timestamp of the key's most recent authenticated request, or `null` if it has never been used. | | `createdAt` | string | ISO 8601 timestamp of when the key was created. | Revoked keys are excluded from this list entirely. ## Create a key ``` POST /keys ``` | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string (1-120 chars) | Yes | A label to help you identify the key later. | | `rateLimitPerMin` | integer (1-120) | No | Requests per minute allowed for this key. Defaults to `60`, capped at `120` regardless of plan. | Each user can hold at most **10 active keys**; creating an 11th (without revoking one first) returns `400 too_many_keys`. ```bash curl -X POST https://app.warmerly.com/api/v1/keys \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "name": "CI pipeline", "rateLimitPerMin": 100 }' ``` ```json { "key": "wmv_7f3a2cdb9e1a4f0c8b6d2e5f7a1c3b9d", "id": "3b1f6e2a-9c4d-4e2a-8b5f-6a2c1d9e0f7b", "prefix": "wmv_7f3a2c", "name": "CI pipeline" } ``` **The `key` field is the only time the raw secret is ever returned.** Warmerly stores only a hash of the key, copy it and store it securely immediately. If you lose it, there is no way to recover it; revoke the key and create a new one instead. A response with HTTP status `201` confirms the key was created. ### Validation errors An invalid body (missing `name`, `name` over 120 characters, or `rateLimitPerMin` outside `1` to `120`) returns `400`: ```json { "error": { "code": "bad_request", "message": "invalid_body", "details": { /* field errors */ } } } ``` ## Revoke a key ``` DELETE /keys/{id} ``` Revokes (soft-deletes) the key. Revoked keys fail authentication immediately on their next request, there is no grace period, and revocation cannot be undone. ```bash curl -X DELETE https://app.warmerly.com/api/v1/keys/3b1f6e2a-9c4d-4e2a-8b5f-6a2c1d9e0f7b \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "revoked": true } ``` If the key doesn't exist, doesn't belong to you, or has already been revoked, this returns `404`: ```json { "error": { "code": "not_found", "message": "not_found", "details": null } } ``` You can revoke the key you're currently authenticating with. The revocation takes effect immediately, so any subsequent request with that key (including further calls in the same script) will fail with `401 unauthorized`. --- # Usage & limits Two endpoints answer "how much have I got left?". Which one you want depends on which kind of limit you mean, and there are three kinds, which behave differently enough that mixing them up produces a wrong number: | Kind | Example | Shape | Read it from | | --- | --- | --- | --- | | **Monthly meter** | Email verifications, AI credits | Month-to-date count vs. a ceiling, resets on the 1st | `GET /usage/quotas` | | **Capacity limit** | Mailboxes, active campaigns, active prospects | A live count, right now, no reset | `GET /billing/me?limits=1` | | **Per-item ceiling** | Leads per campaign | A maximum with no workspace-wide "used" figure | `GET /billing/me?limits=1` | Both endpoints are **pure reads** (neither ever debits an allowance) and both are workspace-scoped, not project-scoped. They describe your whole active workspace, so they take `X-Api-Key` and no `X-Project-Id`. Plain-English background on what each limit means and what happens when you reach one: [Plans, limits and allowances](https://docs.warmerly.com/plans-and-limits). ## Every monthly allowance ``` GET /usage/quotas ``` ```bash curl https://app.warmerly.com/api/v1/usage/quotas \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "monthKey": "2026-09", "plan": "growth-v2", "planName": "Growth", "quotas": [ { "key": "campaignSends", "label": "Campaign sends", "unit": "sends", "tool": "Campaigns", "used": 4120, "limit": null, "remaining": null }, { "key": "verifications", "label": "Email verifications", "unit": "verifications", "tool": "Verify", "used": 812, "limit": 25000, "remaining": 24188 }, { "key": "emailLookups", "label": "Email lookups", "unit": "lookups", "tool": "Email finder", "used": 95, "limit": 10000, "remaining": 9905 }, { "key": "linkedinLookups", "label": "LinkedIn lookups", "unit": "lookups", "tool": "LinkedIn search", "used": 0, "limit": 10000, "remaining": 10000 }, { "key": "leadExports", "label": "Lead exports", "unit": "leads", "tool": "Leads", "used": 1500, "limit": 5000, "remaining": 3500 }, { "key": "placementTests", "label": "Placement tests", "unit": "tests", "tool": "Accounts", "used": 3, "limit": 25, "remaining": 22 }, { "key": "credits", "label": "AI credits", "unit": "credits", "tool": "AI", "used": 40, "limit": 500, "remaining": 460 } ] } ``` | Field | Description | | --- | --- | | `monthKey` | The month these counts cover, `YYYY-MM`. Counts reset when this changes, on the 1st, not on your renewal date. | | `plan` | The plan key whose ceilings apply, or `null` for a workspace with no ceilings (staff / granted unlimited). | | `planName` | Display name for that plan, or `"Unlimited"`. | | `quotas[].key` | Stable identifier: `campaignSends`, `verifications`, `emailLookups`, `linkedinLookups`, `leadExports`, `placementTests`, `credits`. | | `quotas[].used` | Month-to-date count. | | `quotas[].limit` | The ceiling, or `null` for **unmetered**: never read `null` as zero or unknown. Campaign sends are `null` on every paid plan. | | `quotas[].remaining` | `limit - used`, or `null` when the limit is `null`. | The plan resolved here matches the one the write gates enforce: a workspace with no live subscription is held to Free's allowances rather than the plan it used to have, so this endpoint and a `402` from `POST /verify` can never disagree. The per-tool endpoints: [`GET /verify/usage`](https://docs.warmerly.com/verify#usage--quota), [`GET /email-finder/quota`](https://docs.warmerly.com/email-finder), [`GET /leads/quota`](https://docs.warmerly.com/leads#export-quota), are unchanged and still the right call when you only care about one meter. ## Plan capacity ``` GET /billing/me?limits=1 ``` Without `?limits=1` you get the cheap plan/subscription summary and `limits: null`. The flag is opt-in because building the rows runs several aggregate queries, including a `COUNT(DISTINCT email)` across every lead in every active campaign, don't poll it. ```bash curl "https://app.warmerly.com/api/v1/billing/me?limits=1" \ -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` ```json { "plan": "growth-v2", "planName": "Growth", "status": "active", "hasActiveSubscription": true, "currency": "usd", "billingInterval": "month", "currentPeriodEnd": "2026-10-04T00:00:00.000Z", "cancelAtPeriodEnd": false, "limitsGraceUntil": null, "workspaceId": "4ce44435-b783-4523-ba49-fefe23accfc5", "limits": [ { "key": "mailboxes", "label": "Connected mailboxes", "used": 12, "limit": 25 }, { "key": "campaigns", "label": "Active campaigns", "used": 3, "limit": 25 }, { "key": "prospects", "label": "Active prospects", "used": 4210, "limit": 50000 }, { "key": "campaignLeads", "label": "Leads per campaign", "used": null, "limit": 25000 } ], "usage": { "monthKey": "2026-09", "campaignSends": 4120, "campaignLimit": null, "warmupSends": 980, "warmupUnlimited": true } } ``` | Field | Description | | --- | --- | | `limits[].used` | Live count. `null` for a per-item ceiling like `campaignLeads`, which has no single workspace-wide figure. | | `limits[].limit` | The ceiling, or `null` for unlimited. | | `limitsGraceUntil` | ISO timestamp when the over-limit grace period expires, or `null` when the workspace is inside its plan. While it is set, everything keeps running; when it passes, campaign sending and warmup pause until the workspace is back inside its limits or upgraded. | | `status` | The Stripe subscription status (`active`, `trialing`, `past_due`, …). | | `usage.warmupUnlimited` | Warmup is never metered. It is here so a UI can say so rather than drawing an empty bar. | Workspaces belonging to staff or granted unlimited access return `plan: null`, `planName: "Unlimited"` and `limits: null`. ## Quotas are not rate limits A `402 payment_required` means you are out of a monthly allowance; a `429 too_many_requests` means you called too fast. They have different causes, different remedies and different reset behaviour, see [Errors & rate limits](https://docs.warmerly.com/errors). ## Related - [Plans, limits and allowances](https://docs.warmerly.com/plans-and-limits): what the numbers are and how they behave - [Verify](https://docs.warmerly.com/verify), [Email Finder](https://docs.warmerly.com/email-finder), [Leads](https://docs.warmerly.com/leads), the per-tool meters - [Errors & rate limits](https://docs.warmerly.com/errors) --- # Errors & Rate Limits This page documents the two things that apply the same way across almost every endpoint in this API, so each reference page doesn't have to repeat them. Endpoint pages link back here rather than restating this. ## Error response shape Nearly every error response (across every endpoint documented in these docs) is JSON in this shape, with a matching HTTP status code: ```json { "error": { "code": "bad_request", "message": "invalid_body", "details": null } } ``` | Field | Type | Description | | --- | --- | --- | | `error.code` | string | A stable, machine-readable error code, safe to branch on in your integration (see the table below). | | `error.message` | string | A short human-readable reason. Sometimes a slug like `invalid_body`, sometimes a full sentence, treat it as debugging context, not something to parse. | | `error.details` | object \| null | Extra structured context when relevant (e.g. quota numbers, validation field errors). Always present in the response, `null` when there's nothing to add. | Common `error.code` values and their status: | Code | Status | Meaning | | --- | --- | --- | | `bad_request` | 400 | Malformed request body/query, often paired with Zod field errors in `details`. | | `unauthorized` | 401 | Missing, invalid, or revoked API key. | | `forbidden` | 403 | Authenticated, but not allowed to access this resource. | | `channel_not_included` | 403 | Your plan doesn't include the channel (email/LinkedIn/WhatsApp) this action needs. | | `agency_plan_required` | 403 | This feature (API keys, webhooks) requires the Agency plan. | | `not_found` | 404 | The resource doesn't exist, or doesn't belong to you. | | `conflict` | 409 | The request conflicts with the resource's current state. | | `payment_required` / `billing_locked` | 402 | Out of plan quota, or the workspace's billing needs attention. | | `too_many_requests` | 429 | Rate limit exceeded, see below. | | `internal_error` | 500 | Something went wrong on Warmerly's end. Safe to retry. | **Known inconsistency:** an unhandled exception in a route (a bug, not an expected error) falls back to a bare `{ "error": "server_error" }`, a string, not the object shape above, with status `500`. This is rare (every documented error case in these docs uses the object shape) but if you're strictly parsing `error.code`, guard against `error` being a string. There is currently no request ID or correlation ID field in error responses. If you need to reference a specific failed request when contacting support, include the timestamp and endpoint instead. ## Rate limits Rate limiting happens at up to three layers, depending on the endpoint: ### 1. Per-API-key limit (applies to every key) Every API key has its own **per-minute** request limit, checked on every authenticated request regardless of endpoint. Default **60 requests/minute**, configurable up to a cap of **120 requests/minute** per key when you [create it](https://docs.warmerly.com/keys). Exceeding it returns: ```json { "error": { "code": "too_many_requests", "message": "rate_limit_exceeded", "details": null } } ``` with HTTP status `429`. ### 2. Per-endpoint limits (a small number of endpoints) A few endpoints layer an additional, tighter limit on top of the per-key limit, because their abuse case (scraping, credential stuffing) isn't covered by a generous per-minute number: | Endpoint | Limit | Keyed by | | --- | --- | --- | | `GET /leads/search` | 120 requests / 5 minutes | Authenticated user | | `POST /public/deliverability-check` | 10 requests / 60 minutes | IP address | | `POST /public/deliverability-check` with `check: "blocklist"` | the limit above, plus 400 requests / 60 minutes across all callers | IP address, then site-wide | These also return the `429` shape above. ### 3. Unauthenticated request backstop Requests that carry **no** session cookie, `Authorization` header, or `X-Api-Key` (i.e. fully unauthenticated calls, such as `POST /contact`) are capped at **120 requests/minute per IP** as a coarse flood backstop, independent of the limits above. This applies at the edge before your request reaches a route handler. ### What isn't separately rate-limited Session-cookie (dashboard) requests from a logged-in user have no dedicated per-user rate limit beyond the unauthenticated-IP backstop above (which doesn't apply to them once logged in), the practical ceiling for browser-driven dashboard use is whatever each page's own endpoints enforce. If you're building an integration, use an API key rather than reusing a dashboard session, both for correctness and so you get a predictable, documented limit. ## Plan quotas vs. rate limits Don't confuse a rate limit (how fast you can call an endpoint) with a **plan quota** (how much of a metered resource: verifications, lead exports, email-finder lookups, you can use in a calendar month). Quota exhaustion returns `402 payment_required`, not `429`. Monthly allowances reset on the **1st of the month**, not on your subscription's renewal date and not on a rolling window, and they do not roll over. Each metered resource has its own usage endpoint (e.g. [`GET /verify/usage`](https://docs.warmerly.com/verify#usage--quota), [`GET /leads/quota`](https://docs.warmerly.com/leads#export-quota)), and [`GET /usage/quotas`](https://docs.warmerly.com/usage) returns every one of them in a single call. --- # API Changelog Changes to the public Warmerly API (`/api/v1/*`), most recent first. This tracks the **API and these docs** — for product feature announcements, see the in-app changelog at [app.warmerly.com](https://app.warmerly.com/login). ## 2026-09-28 - **Fixed** `PUT /campaigns/{id}/steps` rejecting the documented request body. The endpoint had moved to an internal graph format and answered `400 invalid_body` to the `{ "steps": [...] }` list shown in [Campaigns](https://docs.warmerly.com/campaigns#replace-steps), so no sequence could be written through the API. The documented list is accepted again; `wait` entries are folded into the next step's delay. - **Changed** `GET` and `PUT /campaigns/{id}/steps` now return `steps`, the sequence in send order, as documented, alongside the graph fields the dashboard uses. - **Added** the documentation for language models: [/llms.txt](https://docs.warmerly.com/llms.txt) (an index of every page), [/llms-full.txt](https://docs.warmerly.com/llms-full.txt) (the whole documentation and API reference as one Markdown file) and a Markdown version of every page at `.md` (for example [/campaigns.md](https://docs.warmerly.com/campaigns.md)). See [Use with AI](https://docs.warmerly.com/ai#documentation-for-llms). ## 2026-09-12 Documentation pass against the live API: every documented endpoint was called with a real API key and checked, rather than re-read. - **Corrected** [Suppression](https://docs.warmerly.com/suppression). `GET /suppression` (including `?format=csv`) and `DELETE /suppression` were documented as customer endpoints but are staff-only and return `404` for any customer key, Agency included. The page now documents `POST` (the one endpoint you can call) and says where removal requests go. - **Removed** `GET/POST /inbox/templates` and `PATCH/DELETE /inbox/templates/{id}` from [Inbox](https://docs.warmerly.com/inbox). Those routes do not exist and never did. - **Corrected** the quota-reset claim in [Errors & rate limits](https://docs.warmerly.com/errors): monthly allowances reset on the **1st of the month**, not on your subscription's renewal date. - **Documented** [Usage & limits](https://docs.warmerly.com/usage): `GET /usage/quotas` returns every monthly allowance in one call, and `GET /billing/me?limits=1` returns plan capacity. The first is promoted from internal dashboard plumbing to supported API. - **Documented** many endpoints that were live but absent from this reference: - [Accounts](https://docs.warmerly.com/accounts): bulk connect, provider detection, connection testing, DNS checks, placement tests, blocklist status, per-mailbox stats/events/warmup log, warmup toggle, send test, OAuth reconnect, channel limits. - [Campaigns](https://docs.warmerly.com/campaigns): readiness, message preview, duplicate, cross-campaign lead list, per-lead email history, enrichment retry, lead research. - [Warmup](https://docs.warmerly.com/warmup): worker health, and mailbox health alerts (`GET /alerts`). - [Leads](https://docs.warmerly.com/leads): exact match counts (`GET /leads/count`) and LinkedIn people search. - [Verify](https://docs.warmerly.com/verify): send tests, the deliverability-grade check for catch-all domains. - [Workspaces & Projects](https://docs.warmerly.com/workspaces): project stats, workspace activation, logo, invite revocation. - **Documented** `X-Workspace-Id` and the three request scopes (account, workspace, project) in [Authentication](https://docs.warmerly.com/authentication). Workspace-scoped calls previously looked project-scoped, so a key serving several workspaces could silently read the wrong one. - **Added** an [all-DNS-records checklist](https://docs.warmerly.com/guides/dns-records) covering MX, SPF, DKIM, DMARC and the tracking CNAME together, plus what Warmerly's own check does and does not look at. - **Fixed** in-page anchor links across these docs. Headings carried no `id`, so every `#section` link silently landed at the top of the page. - No API behaviour changed in this entry. ## 2026-08-19 - **Documented** the [Leads](https://docs.warmerly.com/leads), [Suppression](https://docs.warmerly.com/suppression), and [Webhooks](https://docs.warmerly.com/webhooks) endpoints for the first time. These were live in the API but previously undocumented. - **Added** this changelog and a shared [Errors & Rate Limits](https://docs.warmerly.com/errors) reference page, consolidating error-shape and rate-limit details that were previously scattered across (or missing from) individual endpoint pages. - **Added** an explicit statement of which routes are deliberately excluded from these docs, see [What's not documented here](https://docs.warmerly.com/#whats-not-documented-here) on the overview page. - No API behavior changed as part of this entry. This was a documentation-only pass (tracked as [Octelis/warmerly#61](https://github.com/Octelis/warmerly/issues/61)). ## Deprecation policy Warmerly is a small, actively developed API, so this policy is intentionally simple: - **Breaking changes** (removing a field, changing a field's type or meaning, changing required parameters) ship as a **new endpoint or a new path** rather than mutating an existing one in place. Existing integrations keep working unchanged. - **Deprecated endpoints** get a minimum of **90 days' notice** before removal, announced here in this changelog, before they stop working. Deprecated endpoints continue to function normally during the notice period. - **Additive changes** (new optional fields, new endpoints, new optional query parameters) are not considered breaking and may ship without advance notice, always code defensively against unknown extra fields in a JSON response. - Security fixes (e.g. tightening an input validator that was incorrectly permissive) are exempt from the notice period when a delay would leave a real vulnerability open.