beehiiv runs one REST generation only: v2, based at api.beehiiv.com/v2 and current since December 2, 2022. It covers roughly two dozen resource families, subscriptions, posts, segments, automations, webhooks, polls, podcasts and beehiiv’s own ad network, behind a bearer token and one organisation-wide budget of 180 requests per minute. The MCP story is the unusual part: beehiiv shipped a first-party server on March 24, 2026, opened read access to every plan including free Launch, and added write actions on June 16, 2026 – ahead of most newsletter platforms and most transactional ESPs alike.
Model Context Protocol is how an AI client reaches a product’s data and actions without a bespoke integration. Most ESPs in 2026 have nothing first-party. beehiiv is one of the few exceptions, and its entitlement model is more generous than its own API gating would suggest.
beehiiv hosts a remote MCP server at mcp.beehiiv.com/mcp. The documentation is explicit: “All beehiiv users have access to the beehiiv MCP, with no upgrade required”, while “Write actions, creating, editing, and managing content, require a paid beehiiv plan.” Read-only agents run on free Launch at $0/mo; write access starts with Scale at $43/mo. An agent can draft an entire issue, but publishing and scheduling stay in the app.
One first-party server, two independent open-source wrappers and a Zapier bridge. Only the official server reaches beehiiv’s growth and monetisation surfaces; the rest wrap the public v2 REST API and inherit its plan gates and its 180/minute ceiling.
Remote hosted server at mcp.beehiiv.com/mcp, with ?account=N for multiple workspaces. Setup guides ship for Claude, Claude Code, Cursor and Codex, plus a generic path for any remote-MCP client.
Independent open-source wrapper over the v2 REST API, indexed on mcpservers.org. Self-hosted, so the key stays on your machine.
Narrow read-only server exposing list_publications, list_posts and get_post.
Reaches beehiiv’s Zapier triggers and actions. Worth it for chaining to the other 9,000 Zapier apps, not for beehiiv access itself.
The procurement question is what an agent can do unsupervised on your account, and beehiiv’s answer is unusually well bounded. Content, audience, growth, monetisation, automations, podcasts and website management are reachable; publishing or scheduling a post and activating an automation must happen in the app; sponsorship and paywall data are read-only; Stripe payment data is unreachable. An agent drafts, a human presses the button, so a misconfiguration cannot mail your list by accident. Compare Kit, MailerLite and Mailchimp, where agent access still runs through community wrappers with no vendor-defined write boundary.
Everything here is REST over HTTPS returning JSON. beehiiv exposes no SMTP relay and no transactional endpoint, so the API is the entire programmable surface, see the SMTP settings tab for why that absence is architectural.
| Base URL | https://api.beehiiv.com/v2 |
|---|---|
| Generation | v2 ONLY SUPPORTED · since December 2, 2022 |
| Response format | JSON, enveloped, payload sits under data |
| Authentication | Authorization: Bearer <token>, or OAuth2 for distributable apps |
| Pagination | Offset – page, limit, direction, order_by |
| Page size | Default 10, maximum 100 |
| Rate limit | 180 req/min per organisation |
| Bulk extraction | Exports resource, asynchronous, not pagination |
| Programmatic send | Create post endpoint, Max $96/mo and Enterprise only |
| Request timeout | Not documented |
The resource model is publication-scoped and almost entirely uniform: /v2/publications/{publicationId}/{resource}. The first call any integration writes is therefore GET /v2/publications to resolve the ID, which looks like pub_ plus a UUID. A request outside a scoped key’s publications returns 404 Not Found, not a permission error, which sends developers hunting for a missing record when the problem is the key. Capability splits by plan: reading and subscriber management on free Launch, webhooks from Scale, dispatching a newsletter only on Max.
The default path. Keys live under Settings › Workspace Settings › API and travel as Authorization: Bearer <token>. Two constraints bite first: “You must be a workspace Owner or Admin role to access your API keys”, and Stripe Identity verification is mandatory before a key can be generated at all. The key is displayed once, “This is the only time you will see this API key.” There is no reveal-later screen, only rotation.
For anything distributed to other people’s publications, beehiiv’s guidance is unambiguous: “Building an integration? Use OAuth2 instead of API keys.” Grants are granular – posts:read, posts:write, subscriptions:write, publications:read, automations:read, segments:read, webhooks:write and others, so a reporting tool never holds write capability and revocation is per-install. An API key is fine for an internal script; for anything a customer installs, OAuth2 is the only defensible choice.
Two silent-failure modes share one symptom. A publication-scoped key querying an out-of-scope publication returns 404, not 403, so the client logs a missing resource. An OAuth2 token missing posts:write fails at the mutation rather than the token exchange, so the connection test passes and the nightly job breaks. Assert on the returned object, not the status code alone.
| Limit | Value | Notes |
|---|---|---|
| API requests | 180 per minute | Documented as “180 requests per minute on a per-organization basis” |
| Scope of the bucket | Per organisation | Not per key, not per publication, every job shares it |
| Over-limit response | 429 Too Many Requests | beehiiv recommends exponential backoff and queueing, not retries |
| Budget headers | RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset | Bare prefix, not X-RateLimit-. Reset is epoch seconds |
| Page size ceiling | 100 records | Default is 10, so an unset limit costs 10x |
| Email send volume | Subscriber-capped, not rate-capped | All tiers advertise “Unlimited Email Sends” within the ceiling |
The workaround is arithmetic, not cleverness. At 100 records per page a 50,000-subscriber walk is 500 calls, nearly three minutes of polling during which nothing else on the account can run. Hence the separate Exports resource: fire an asynchronous export for anything bulk, and use Bulk Subscription Updates rather than one POST per record. Middleware that auto-detects X-RateLimit-Remaining sees nothing here, so backoff logic has to be explicit.
No hourly send rate, per-message recipient cap or message size limit appears in any official document, and Enterprise is described only as having “custom limits”.
beehiiv maintains exactly one, and its beta warning should be taken literally. Everything else on a package registry is community work, however official the name looks.
| Language | Package | Install | Repo |
|---|---|---|---|
| TypeScript / JavaScript | @beehiiv/sdk BETA | npm i @beehiiv/sdk | beehiiv/typescript-sdk |
Published at v0.1.6, last updated December 3, 2025, warning that “there may be breaking changes between versions without a major version update”. Semantic versioning guarantees nothing here, so write "@beehiiv/sdk": "0.1.6", never "^0.1.6". It is generated from the OpenAPI specification via Fern, so it tracks the reference closely but lags feature announcements.
There is no official Python client. PyPI carries community packages including beehiiv and beehiiv-python-client, neither published by beehiiv, and beehiiv’s GitHub organisation holds no Python repository. For Python the honest recommendation is plain requests against a stable, offset-paginated REST API, as the example below does. Other ecosystems are served by Zapier, Make and Pipedream connectors rather than SDKs.
Roughly two dozen resource families, all nested under a publication except the publication list itself. The live reference is at developers.beehiiv.com/api-reference; the older /docs/v2/ tree returns 404, so any tutorial linking there is a documentation generation stale.
| Resource | Methods | Description |
|---|---|---|
| Publications /v2/publications | GET | Every publication a key can reach. The first call any integration makes. |
| Publication /v2/publications/{id} | GET | One publication, with optional statistics expansion. |
| Posts /v2/publications/{id}/posts | GET, POST | On POST this is the Send API, Max and Enterprise only. Returns 201 with an id and preview_url. |
| Post /v2/publications/{id}/posts/{postId} | GET, PUT, DELETE | Reads, updates or deletes a single post. |
| Subscriptions /v2/publications/{id}/subscriptions | GET, POST | Only email is required; options cover welcome mail, five UTM fields, custom_fields and tier. |
| Subscription /v2/publications/{id}/subscriptions/{subId} | GET, PUT, PATCH, DELETE | Reads, updates or deletes one subscription by ID. |
| Bulk Subscription Updates /v2/publications/{id}/bulk_subscription_updates | GET, POST | Batch mutation, so a migration does not spend the 180/minute budget one record at a time. |
| Subscription Tags /v2/publications/{id}/subscription_tags | GET, POST, PUT, DELETE | The tag vocabulary applied to subscribers for segmentation. |
| Custom Fields /v2/publications/{id}/custom_fields | GET, POST, PUT, DELETE | Define the field first: a value written to an undeclared field is dropped. |
| Segments /v2/publications/{id}/segments | GET, POST, PUT, DELETE | Saved audience definitions. Member lists are fetched separately, not inlined. |
| Automations /v2/publications/{id}/automations | GET | Read-only over the API. Activating an automation is a UI-only action. |
| Automation Journeys /v2/publications/{id}/automations/{autoId}/journeys | GET, POST | Enrols a subscriber and inspects their progress. |
| Webhooks /v2/publications/{id}/webhooks | GET, POST, PUT, DELETE | Registers an endpoint against 26 event types. Scale and above. |
| Newsletter Lists /v2/publications/{id}/newsletter_lists | GET, POST, PUT, DELETE | Sub-lists, so a subscriber can take some sends and not others. |
| Exports /v2/publications/{id}/exports | GET, POST | Asynchronous bulk extraction, the alternative to paginating a large list. |
Five more families follow the same scheme: Tiers, Referral Program, Polls, Podcasts and Ad Network, a monetisation surface with no equivalent in a transactional API like Postmark or Amazon SES.
Plain requests, because there is no official Python SDK. Note the explicit status on the send.
import os
import requests
BASE = "https://api.beehiiv.com/v2"
PUB_ID = os.environ["BEEHIIV_PUBLICATION_ID"] # pub_xxxxxxxx-...
HEADERS = {
"Authorization": f"Bearer {os.environ['BEEHIIV_API_KEY']}",
"Content-Type": "application/json",
}
def add_subscriber(email):
"""Works on every plan, free Launch included."""
r = requests.post(
f"{BASE}/publications/{PUB_ID}/subscriptions",
headers=HEADERS,
json={"email": email, "reactivate_existing": False,
"send_welcome_email": True, "utm_source": "website"},
timeout=30,
)
r.raise_for_status()
return r.json()["data"]
def send_post(title, paragraphs):
"""THE SEND API. Max ($96/mo) or Enterprise only.
Since 2026-08-06, omitting status creates a DRAFT.
"""
r = requests.post(
f"{BASE}/publications/{PUB_ID}/posts",
headers=HEADERS,
json={"title": title,
"blocks": [{"type": "paragraph", "plaintext": p}
for p in paragraphs],
"status": "confirmed"},
timeout=60,
)
r.raise_for_status() # 402/403 = plan lacks the Send API
return r.json()["data"]
The 429 branch reads RateLimit-Reset as epoch seconds and sleeps to that instant rather than guessing a delay, which matters when the whole organisation shares one bucket.
// beehiiv v2 REST. There is no SMTP transport to fall back on.
const BASE = "https://api.beehiiv.com/v2";
const PUB_ID = process.env.BEEHIIV_PUBLICATION_ID; // pub_xxxxxxxx-...
const headers = {
Authorization: `Bearer ${process.env.BEEHIIV_API_KEY}`,
"Content-Type": "application/json",
};
async function call(path, init = {}) {
const res = await fetch(`${BASE}${path}`, { ...init, headers });
if (res.status === 429) {
// 180 req/min per ORGANISATION; reset is Unix epoch seconds
const reset = Number(res.headers.get("RateLimit-Reset"));
const waitMs = Math.max(0, reset * 1000 - Date.now()) + 250;
await new Promise((r) => setTimeout(r, waitMs));
return call(path, init);
}
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
return res.json();
}
// limit caps at 100, default is only 10 - always set it explicitly.
export async function* allSubscribers() {
let page = 1;
for (;;) {
const body = await call(
`/publications/${PUB_ID}/subscriptions?page=${page}&limit=100`
);
yield* body.data;
if (page >= body.total_pages) return;
page += 1;
}
}
// THE SEND API - Max ($96/mo) or Enterprise. Omit status and you
// get a draft, silently, with a 201 and a real post ID.
export async function sendPost(title, paragraphs) {
const { data } = await call(`/publications/${PUB_ID}/posts`, {
method: "POST",
body: JSON.stringify({
title,
blocks: paragraphs.map((p) => ({ type: "paragraph", plaintext: p })),
status: "confirmed",
}),
});
return data;
}
The pricing grid lists “API Access (excluding Send API)” in the free Launch column and Send API only in the Max column at $96/mo; the endpoint reference states that POST /v2/publications/{publicationId}/posts is “available to publications on the Max and Enterprise plans.” So you can sign up free, generate a key, sync subscribers, register webhooks and build most of an integration before discovering that the one thing you were building toward costs more than twice the Scale tier you budgeted for.
Posts created without an explicit status now default to draft instead of publishing immediately: “To maintain auto-publish behavior, requests must explicitly include status: confirmed.” This is the dangerous class of breaking change, because nothing errors: the API returns 201 Created with a real post ID and a preview_url, logs look healthy, and the newsletter silently stops going out. Send status explicitly and assert on the returned status field, not the HTTP code.
The documentation states the limit without hedging: “The beehiiv email structure is fixed…you cannot replace the [header] or standard footer elements required for CAN-SPAM/GDPR compliance. Additionally, we do not currently offer the ability to send 100% custom HTML email.” The endpoint mirrors the Post Builder rather than accepting a MIME body, which is why blocks is idiomatic even though body_content takes HTML. If you need control of the markup, headers or unsubscribe mechanics, you have reached the edge of what beehiiv does.
180 requests per minute is shared across the whole organisation, not per key, not per publication, so a nightly CRM sync and a live dashboard draw from one bucket. Meanwhile the default page size is 10 against a ceiling of 100, so a client that forgets limit burns ten times the requests it needs. Set limit=100 on every list call and read the bare RateLimit- headers, not the X-RateLimit- prefix most clients look for.
Only workspace Owners and Admins can reach API keys, Stripe Identity verification is mandatory before one can be generated, and the key is shown once. Separately, two documentation generations are still linked from across the web: the live reference sits at developers.beehiiv.com/api-reference/, while the older /docs/v2/ tree returns 404. A tutorial is current only if its calls hit api.beehiiv.com with /v2/ in the path and an Authorization: Bearer header.
status begin defaulting to draft.Release notes live at product.beehiiv.com. No v2 endpoint has been deprecated to date; the breaking change of 2026 was a default value, not a removal, which is exactly why it caught so many integrations.
Read and subscriber-management access is free. The pricing grid lists API Access (excluding Send API) on free Launch, so you can list publications, create and update subscribers, read posts and query segments at $0/mo inside the 2,500-subscriber cap. Two things cost money: webhooks need Scale at $43/mo, and the Create post endpoint that dispatches a newsletter needs Max at $96/mo.
Settings › Workspace Settings › API. Two prerequisites catch people out: you must hold the workspace Owner or Admin role, and Stripe Identity verification is mandatory first. The key is displayed exactly once, so store it immediately. Keys can be scoped to specific publications, and a request outside that scope returns 404 Not Found rather than a permission error.
It is not a separate product: it is POST /v2/publications/{publicationId}/posts, the Create post endpoint, which takes a title plus blocks or body_content and dispatches a real newsletter. The reference says it is “available to publications on the Max and Enterprise plans” – $96/mo and up, since it moved from Enterprise-only on August 6, 2026. It cannot mail an address outside your subscriber list.
180 requests per minute, documented as “on a per-organization basis”, one bucket for the whole account, not per key and not per publication. Exceeding it returns 429. Three headers track the budget and use the bare prefix, not the common X- form: RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset. No per-plan differentiation is published.
You can send a newsletter on Max and above through the Create post endpoint. You cannot send transactional email at all, no password resets, no receipts, on any plan, and there is no SMTP relay: beehiiv publishes no hostname, port or credentials anywhere. Pair beehiiv with Postmark or Amazon SES on a separate subdomain for that traffic.
Yes, first-party and hosted, at https://mcp.beehiiv.com/mcp – append ?account=N if you hold multiple workspaces. Setup guides ship for Claude, Claude Code, Cursor and Codex. Read access is available on every plan including free Launch; write actions require a paid plan from Scale upward. Publishing, scheduling and activating an automation stay in the app, and Stripe payment data is unreachable.
This review follows our email infrastructure testing methodology. We disclose affiliate relationships in our editorial independence policy.