Warmerlydocs
Get started

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.

Ways to authenticate

MethodUsed byCredentialPlan
API keyYour own code, scripts and automation toolsX-Api-Key: wmv_... headerAgency
Signed-in sessionThe Warmerly dashboard in your browserSession cookieAny
Mobile sessionThe Warmerly Android appAuthorization: Bearer <session token>Any
OAuth connectionAI assistants such as Claude, ChatGPT and Cursor, through the MCP serverAccess token starting wm_at_Any
Transactional sending keyThe transactional email APIAuthorization: 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.
  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.

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

HeaderRequiredDescription
X-Api-KeyAlwaysYour API key secret.
X-Project-IdMost endpointsThe 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 endpoints.
X-Workspace-IdOptionalWhich 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.
Shell
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:

ScopeIdentified byExamples
Accountthe key itself/keys, /workspaces, /projects, /alerts
WorkspaceX-Workspace-Id, else your active workspace/suppression, /usage/quotas, /billing/me, /accounts/limits, /inbox/*
ProjectX-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 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), and the approval screen is explained in How do I connect, check or revoke an AI app?.

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}. 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, 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?.

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 } }
Statuserror.codeCause
401unauthorizedKey missing, unknown or revoked.
403agency_plan_requiredThe workspace the request acts on is not on Agency.
403account_suspendedThe account is suspended.
400bad_requestX-Project-Id missing or not a valid UUID.
429too_many_requestsThe key's per-minute limit was exceeded.

The full list is in Errors & Rate Limits.

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.

Summarize with AI

Markdown version for LLMsllms.txt

Something unclear or out of date? Ask Warmi in the chat, or email support@warmerly.com.