Connect beehiiv to Fondoo

Live5 min readUpdated

beehiiv in Fondoo: what your AI agent can do with it, what to set up first, the permissions it needs and its limits.

In beehiiv open Settings → Workspace Settings → API (workspace Owner or Admin; beehiiv requires Stripe identity verification first), create an API key that can access the publication, and copy that publication's ID (pub_...) from the Publication ID section below the keys; one Fondoo connection covers one publication. API keys carry no finer permission scopes. Subscriber sync works on every plan within beehiiv's per-key limit (Free 30 requests/minute); creating draft posts needs the Max or Enterprise plan and confirming (sending) them the Pro, Max or Enterprise plan per beehiiv's Send API docs.

Official documentation: https://developers.beehiiv.com/api-reference

Use add_connection_key without fields for a signed, one-use secure paste page. Then call test_connection and inspect confirmed versus unknown permissions. Direct tool credentials carry a chat-log warning. list_connections never returns credentials.

Auth: api_key (Authorization: Bearer <key>; credential fields apiKey (secret) and publicationId (not secret, format pub_ + UUID)). Category: email. Required provider scopes: none for API keys (beehiiv's OAuth scopes such as subscriptions:write and posts:write do not apply to API keys); a key limited to other publications fails with 401/403/404.

Capabilities are discoverable with list_connector_manifests; invoke them through connector_action. Writes retain shared Fondoo scopes, approvals, dry runs, audit, events and metering. Use rotate_connection_key before expiry and delete_connection to remove stored credentials; revoke upstream credentials separately.

What Fondoo does with beehiiv

Normalized email capabilities:

  • audiences.list (read): the publications the key can see (GET /publications, first 100), with memberCount = beehiiv stats.active_subscriptions.
  • subscribers.list (read): subscriptions of the connection's publication with beehiiv's cursor pagination (limit is capped at beehiiv's maximum of 100 per call; nextCursor is beehiiv's next_cursor, null when has_more is false). Status mapping: active → subscribed, pending (awaiting double opt-in) → pending, inactive (unsubscribed) → unsubscribed, invalid → cleaned, validating / needs_attention / paused → other. The status filter maps subscribed → active and unsubscribed → inactive.
  • subscribers.upsert_batch (write): for each member, one lookup (GET /subscriptions?email=), then:
    • subscribed, not found: create with reactivate_existing:false, send_welcome_email:false, utm_source:"fondoo", and no double_opt_override (the publication's own double opt-in setting applies, so beehiiv itself may send its confirmation email and report the person pending); tags are then added. A create that comes back inactive/invalid is reported skipped_provider_unsubscribed.
    • subscribed, found inactive or invalid: skipped_provider_unsubscribed, nothing written. Found needs_attention/paused: unchanged. Found active/pending/validating: tags are added (outcome updated) or nothing happens (unchanged). Tags are additive; beehiiv tags are never removed.
    • unsubscribed: found and not already inactive → PUT /subscriptions/by_email/{email} with unsubscribe:true (updated); not found or already inactive → unchanged. Nobody is created or deleted.
    • name is accepted but not stored (beehiiv subscriptions have no name field; names live in publication-specific custom fields).
    • One execute makes at most 25 beehiiv requests (up to 3 per member); members beyond that budget come back as outcome:"error", message:"batch_limit" and must be resent in a later call. 401/403 and 429 abort the whole batch (permission_denied / rate_limited); other per-member failures are error rows.
  • listId is optional everywhere; when given it must equal the connection's publicationId, otherwise the call is rejected (connect other publications as separate connections).
  • campaigns.create_draft (write): creates a post with status:"draft" (never scheduled or published), body_content = the HTML, email_settings.email_subject_line / email_preview_text / reply_to_address (must be a verified reply-to address in beehiiv, otherwise beehiiv returns 422), and recipients: { email: { tier_ids: ["all"] } } (email to free and premium tiers, no web target). fromName is ignored: beehiiv's sender_name is a preset key configured in beehiiv, not free text. beehiiv builds posts asynchronously; the returned campaignId is the post_... ID.
  • campaigns.send (destructive): reads the post first and refuses unless it is a draft whose platform is not web-only, then PATCHes it to status:"confirmed" (with scheduled_at when scheduleAt is given; otherwise beehiiv publishes it now). This is irreversible: beehiiv does not allow moving a confirmed post back to draft. Returns sending or scheduled.

Vendor-native capabilities: publications.get, subscriptions.get (by email, with tags and custom fields expanded), subscriptions.add_tags (by subscriptionId or email; beehiiv creates missing tags; max 100 unique tags per publication), posts.list, posts.get (default expand[]=stats), segments.list, custom_fields.list, tiers.list (optional prices). All take bounded, validated inputs; page-based lists return page, totalPages, totalResults.

Not implemented: subscription delete (beehiiv: "cannot be undone"; it recommends unsubscribing instead), tag removal, bulk subscription imports, segment/custom-field/tier writes, post delete/update beyond confirming a draft.

API endpoints used

Limits and uncertainties

  • Rate limit: beehiiv documents per-key limits per 60 s window of 30 (Free), 180 (Lite), 500 (Pro), 800 (Enterprise). Fondoo's local budget is 10 executes per minute because one execute may make up to 25 requests; 429 surfaces as rate_limited with Retry-After when sent.
  • Uncertain: plan gating of the Send API. The Create Post page says Max and Enterprise; the Update Post page says Pro and Enterprise; the rate-limit page uses Free/Lite/Pro/Enterprise names. A plan without access returns an error that Fondoo reports as permission_denied (401/403) or provider_error.
  • Uncertain: whether status:"confirmed" without scheduled_at sends the email immediately (the docs say the post is published; email delivery follows recipients).
  • Uncertain: list-subscriptions expand[] does not list tags (only stats, custom_fields, referrals, newsletter_lists) although the Subscription schema mentions expand: [tags]; Fondoo does not request it, so subscribers.list returns tags only if beehiiv includes them (normally []).
  • Uncertain: custom_fields.list documents limit/page only in the response; they are forwarded only when supplied.
  • Uncertain: paused appears in the subscription status enum without a description; it maps to other and is never modified.
  • The Create Subscription page does not say what happens when the email already exists; Fondoo always looks the person up first, so create is only called for unknown addresses.
  • beehiiv's bulk subscription create returns only an asynchronous import ID with no per-member result, so Fondoo uses single creates (bounded per execute) instead.

Compliance notes

  • Fondoo never re-subscribes someone beehiiv reports inactive (unsubscribed) or invalid; reactivate_existing is always false (beehiiv: "should be used only if the subscriber is knowingly resubscribing").
  • Fondoo never overrides the publication's double opt-in (double_opt_override is never sent) and never sends beehiiv's welcome email.
  • Core only pushes people who completed Fondoo's own double opt-in. Sending a campaign is destructive and needs owner approval for agents. beehiiv adds its own unsubscribe handling and footer to posts.