MailerDot Developer Documentation

The MailerDot API, MCP server, and agent-readable resources — every U.S. city we publish, its daily editions, weather, and census facts. Read-only, no key, no sign-up, CORS open.

Base URL: https://mailerdot.com · OpenAPI 3.1 spec · MCP server · This page as markdown

Authentication

None. Every endpoint below is public and read-only — one exception, POST /api/subscribe — and needs no key, token, account, or sign-up. There is no sandbox because there is nothing to break: the read endpoints cannot mutate anything, so you can develop against production directly.

Quickstart

# 1. Find a city
curl -s 'https://mailerdot.com/api/cities'

# 2. Read its latest edition as markdown
curl -s 'https://mailerdot.com/austin-texas.md'

# 3. Search every archive
curl -s 'https://mailerdot.com/api/search?q=farmers+market&limit=3'

City slugs

Every endpoint is keyed by a slug of the form `{city}-{state-name}`, lowercased and hyphenated — `austin-texas`, `san-francisco-california`, `new-york-new-york`. The state is the full name, not the postal abbreviation. Fetch https://mailerdot.com/api/cities for the authoritative list.

API endpoints

MethodPathReturns
GET/api/citiesEvery city with a published edition, grouped by state.
GET/api/cities-censusCensus-tracked cities, filterable by population and state.
GET/api/city/{slug}One city: subscriber count, archive index, census snapshot, events, directory.
GET/api/archive/{slug}/{date}One past edition. Append `.md` to the date for markdown instead of JSON.
GET/api/searchFull-text search across every archived edition, with highlighted snippets.
GET/api/weather/{slug}Today's forecast — the stored snapshot the edition used, or a live fetch.
GET/api/facts/{slug}Schema.org Dataset facts for a city: newsletter metadata plus ACS demographics.
GET/api/territoriesWhether a town can be leased and what it costs. No query returns the taken list.
GET/api/oembedoEmbed provider for city and edition pages (rich iframe embeds).
POST/api/subscribeSubscribe an address to a city. The only open write endpoint.

Full parameters and response schemas: https://mailerdot.com/openapi.json

Error responses

Every failure answers with application/problem+json (RFC 9457) — never an HTML page, on any path under /api/, including ones that do not exist. Branch on code; it is stable. resolution says what to do next, and issues[] lists per-field failures on a validation error.

CodeHTTPMeaningWhat to do
city_not_found404No MailerDot city for that slugFetch https://mailerdot.com/api/cities for every city with a published edition. A U.S. city with no MailerDot edition yet has no data to return; subscribing to it creates one.
conflict409Request conflicts with current stateRe-read the resource to see its current state, then decide whether to retry.
edition_not_found404No edition published for that dateFetch https://mailerdot.com/api/city/{slug} for the dates that exist. Editions publish each morning in the city's own timezone, so today's may not exist yet.
endpoint_not_found404No such API endpointEvery public endpoint is listed in https://mailerdot.com/openapi.json and https://mailerdot.com/.well-known/api-catalog. Human-readable docs: https://mailerdot.com/developers.
forbidden403Not permittedThe credential is valid but does not grant this action. Nothing to retry.
internal_error500Unexpected server errorRetry once; this is usually transient. If it persists, report it at https://mailerdot.com/contact with the request path and time.
invalid_json400Request body is not valid JSONSend a JSON body with `Content-Type: application/json`, then retry.
invalid_slug400City slug is not well-formedSlugs are `{city}-{state-name}`, lowercased and hyphenated — `austin-texas`, `san-francisco-california`. List valid slugs at https://mailerdot.com/api/cities.
method_not_allowed405HTTP method not allowedUse one of the methods in the `Allow` response header. Per-endpoint methods are in https://mailerdot.com/openapi.json.
missing_slug400City slug is missingPut a city slug in the path, e.g. `/api/city/austin-texas`. List valid slugs at https://mailerdot.com/api/cities.
not_found404Resource not foundCheck the identifier and retry. The available endpoints are listed at https://mailerdot.com/openapi.json.
payload_too_large413Request body is too largeSend a smaller body. The per-endpoint limit is in the `detail` field.
rate_limited429Rate limit exceededBack off and retry after the `Retry-After` header's number of seconds.
service_misconfigured503Service is misconfiguredThe deployment is missing required configuration and cannot serve the API. This is our problem, not the caller's — retry later or report it at https://mailerdot.com/contact.
unauthorized401Authentication requiredThis endpoint is not part of the public API. Sign in at https://mailerdot.com/operators — the public, unauthenticated surface is documented at https://mailerdot.com/developers.
upstream_error502An upstream service failedA third-party dependency failed or timed out. Retry with backoff.
validation_error400Request validation failedRead `issues[]` for the per-field failures, fix the request, and retry. Request shapes are documented at https://mailerdot.com/openapi.json.
weather_unavailable404No weather available for that cityThe city resolved but neither a stored snapshot nor a live forecast was available. Retry later; weather is refreshed with each morning's edition.

Markdown for agents

Every page has a markdown twin. Append .md to the path, or send Accept: text/markdown. Responses carry an X-Markdown-Tokens header with a rough token estimate.

  • https://mailerdot.com/{slug}.md — A city page: latest edition, archive index, census table.
  • https://mailerdot.com/{slug}/{YYYY-MM-DD}.md — One dated edition, in full.
  • https://mailerdot.com/cities.md — The whole city directory.
  • https://mailerdot.com/states/{state}.md — Every tracked city in one state, by population.
  • https://mailerdot.com/feed.md — The 30 most recent editions across all cities.
  • https://mailerdot.com/developers.md — This page.

MCP server

https://mailerdot.com/mcp speaks the Model Context Protocol over streamable HTTP, unauthenticated. Point any MCP client at it:

{
  "mcpServers": {
    "mailerdot": {
      "url": "https://mailerdot.com/mcp"
    }
  }
}

Tools:

  • list_cities — Every city with an active newsletter, grouped by state.
  • get_city — City overview: subscribers, census demographics, recent editions.
  • get_archive — Read a past edition as markdown.
  • search_archives — Full-text search across every edition.
  • get_weather — Today's weather for a city.

It also serves resources/list, resources/templates/list, resources/read, and prompts/list.

Machine-readable discovery

  • OpenAPI 3.1 specification application/json — The full contract: every endpoint, schema, and error code. Generate a client from it.
  • MCP server application/json — Model Context Protocol over streamable HTTP. Tools, resources, and prompts.
  • API catalog (RFC 9727) application/linkset+json — Linkset pointing at everything on this list. The standard discovery entry point.
  • Agent Skills index application/json — A SKILL.md an agent can load to learn the URL shapes without crawling for them.
  • llms.txt text/plain — What MailerDot is, in one page, written for a language model.
  • llms-full.txt text/plain — The long form: product, editorial policy, operator terms, and API notes.
  • RSS feed application/rss+xml — The most recent editions across every city.
  • Sitemap index application/xml — Every indexable URL: cities, states, and dated editions.

Limits and conventions

  • No API key, no account, no rate limit on the read endpoints. Be reasonable and cache what you fetch — responses carry real `Cache-Control` headers, so honouring them costs you nothing.
  • Every read endpoint sends `Access-Control-Allow-Origin: *`, so browser-side agents can call them directly.
  • Markdown responses carry an `X-Markdown-Tokens` header with a rough token estimate, so you can decide whether to fetch a full edition or stop at the summary.
  • Editions publish each morning in the city's own timezone. Asking for today's edition before it publishes returns a 404 with the `edition_not_found` code, not the previous day's content.
  • Coverage is the United States only.

Support