<!-- API Changelog — https://docs.warmerly.com/changelog -->

# 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 `<page>.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.
