# FlockStack API and MCP reference Everything a FlockStack customer does in the dashboard works through the REST API and the MCP server. Both run the same actions as the dashboard, with the same plan limits, sender rules, pre-send checks, paused accounts and first-send steps. ## Authentication Create an API key on the dashboard's API keys page and send it as `Authorization: Bearer ` to https://eu.flockstack.io/api/v1 or to the MCP server at https://eu.flockstack.io/mcp. - Full access keys can do everything below, including creating more keys. Keep them on a server or in your AI assistant's settings. - Signups only keys can only add contacts (`POST /api/v1/contacts`, MCP tool `add_contact`), for signup forms in website code. That endpoint also answers browsers (CORS). - Every key gets 300 requests a minute across REST and MCP, and some actions have their own limit, for each key and for the account: its keys, connected apps and dashboard share the account's, so more keys don't raise it. Over a limit, the answer is 429 rate_limited. - Keys are stored hashed and shown once. Revoked keys answer 401 unauthorized. An account has up to 20 active keys. - Keys start with `mc_` (United States) or `mc_eu_` (European Union) followed by 43 characters of base64url. An account lives in one region and its keys only work at that region's address. To find keys in text, match `(?., which FlockStack sets up in a few minutes. List cleanup is on unless cleanup.enabled is false. Without a postalAddress, its emails print the server's default if it has one: FlockStack's address on FlockStack Cloud. - `name` (body, string, required): The newsletter's name, shown in emails and on the archive - `slug` (body, string): Lowercase letters, digits and dashes. Default: made from the name, numbered when another newsletter has it. - `imageUrl` (body, string): Square logo, 128×128 or larger: an https:// link - `fromName` (body, string): Name in the From field - `fromEmail` (body, string): The shared address (hello@., set automatically) or an address on a domain added to this account - `replyTo` (body, string): Where replies go. Empty: replies to the shared address go to the account owner. - `postalAddress` (body, string): Printed in the footer of every email. Never set, it's the server's default (FlockStack's address on FlockStack Cloud, none on a self-hosted server); saved empty, there's none and sending waits for one. - `archiveEnabled` (body, boolean): A public page for each sent issue, with a signup form. On for new newsletters: the website goes live after the first issue. - `description` (body, string): One sentence under the name on the archive, 200 characters at most - `author` (body, object): The archive's author page; the author's name is fromName - `author.bio` (body, string): Under the author's name on the archive, 160 characters at most - `author.imageUrl` (body, string): Author photo: an https:// link. The newsletter image otherwise. - `socialLinks` (body, string[]): https:// links shown on the archive, 8 at most - `requireConfirmation` (body, boolean): Confirmed opt-in: new signups get an email with a button and only join once they click it. On for new newsletters. - `cleanup` (body, object): List cleanup at each send: contacts who ignored several issues get a last-chance email instead, and become dormant if they don't answer - `cleanup.enabled` (body, boolean): On for new newsletters - `cleanup.issues` (body, number | null): Ignored issues in a row before the last-chance email, 2 to 100. Default 6. - `cleanup.days` (body, number | null): Days without an open, click or signup, 30 to 3650. Default 180. - `welcome` (body, object): Email sent to each new subscriber. Not sent while signups need confirming. - `welcome.enabled` (body, boolean) - `welcome.subject` (body, string) - `welcome.previewText` (body, string) - `welcome.markdown` (body, string): Markdown - `confirmation` (body, object): The confirmation email for confirmed opt-in. Sent back unchanged, the built-in one stays built-in and follows the name and description. - `confirmation.subject` (body, string) - `confirmation.previewText` (body, string) - `confirmation.markdown` (body, string): Markdown that keeps the button: an HTML link like Confirm ```bash curl -X POST "https://eu.flockstack.io/api/v1/newsletters" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Field notes","postalAddress":"Field Notes Ltd, 1 Main St, Paris, France"}' ``` #### Update a newsletter `PATCH /api/v1/newsletters/{id}` · MCP tool `update_newsletter` · Full access · safe to repeat Changes a newsletter's settings. Send only the fields to change; nested groups (welcome, confirmation, cleanup, author) keep the fields you leave out. An account changes slugs 3 times a day at most: one more answers rate_limited. - `id` (path, string, required): The newsletter's ID or slug - `name` (body, string): The newsletter's name, shown in emails and on the archive - `slug` (body, string): Lowercase letters, digits and dashes, not a name FlockStack keeps like www, api or mail. The shared from address (hello@.) and the archive subdomain follow it. - `imageUrl` (body, string): Square logo, 128×128 or larger: an https:// link - `fromName` (body, string): Name in the From field - `fromEmail` (body, string): The shared address (hello@., set automatically) or an address on a domain added to this account - `replyTo` (body, string): Where replies go. Empty: replies to the shared address go to the account owner. - `postalAddress` (body, string): Printed in the footer of every email. Never set, it's the server's default (FlockStack's address on FlockStack Cloud, none on a self-hosted server); saved empty, there's none and sending waits for one. - `archiveEnabled` (body, boolean): A public page for each sent issue, with a signup form. On for new newsletters: the website goes live after the first issue. - `description` (body, string): One sentence under the name on the archive, 200 characters at most - `author` (body, object): The archive's author page; the author's name is fromName - `author.bio` (body, string): Under the author's name on the archive, 160 characters at most - `author.imageUrl` (body, string): Author photo: an https:// link. The newsletter image otherwise. - `socialLinks` (body, string[]): https:// links shown on the archive, 8 at most - `requireConfirmation` (body, boolean): Confirmed opt-in: new signups get an email with a button and only join once they click it. On for new newsletters. - `cleanup` (body, object): List cleanup at each send: contacts who ignored several issues get a last-chance email instead, and become dormant if they don't answer - `cleanup.enabled` (body, boolean): On for new newsletters - `cleanup.issues` (body, number | null): Ignored issues in a row before the last-chance email, 2 to 100. Default 6. - `cleanup.days` (body, number | null): Days without an open, click or signup, 30 to 3650. Default 180. - `welcome` (body, object): Email sent to each new subscriber. Not sent while signups need confirming. - `welcome.enabled` (body, boolean) - `welcome.subject` (body, string) - `welcome.previewText` (body, string) - `welcome.markdown` (body, string): Markdown - `confirmation` (body, object): The confirmation email for confirmed opt-in. Sent back unchanged, the built-in one stays built-in and follows the name and description. - `confirmation.subject` (body, string) - `confirmation.previewText` (body, string) - `confirmation.markdown` (body, string): Markdown that keeps the button: an HTML link like Confirm ```bash curl -X PATCH "https://eu.flockstack.io/api/v1/newsletters/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"replyTo":"jane@example.com","requireConfirmation":true}' ``` #### Check a slug `GET /api/v1/newsletters/slugs/{slug}` · MCP tool `check_newsletter_slug` · Full access · read-only, safe to repeat Says whether a newsletter can take a slug: available, or taken by another newsletter, reserved by FlockStack or invalid, with the message saving it would answer. Checking doesn't count toward the 3 slug changes a day. - `slug` (path, string, required): The slug to check - `id` (query, string): The newsletter that would take it, by ID or slug: its own slug is available to it ```bash curl "https://eu.flockstack.io/api/v1/newsletters/slugs/6650f1c2e9b1d4a012345678?slug=field-notes" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Send a test of the welcome email `POST /api/v1/newsletters/{id}/welcome-test` · MCP tool `send_welcome_test_email` · Full access · reaches outside FlockStack Sends the saved welcome email to the account owner's address, switched on or not. It counts toward the plan's emails. - `id` (path, string, required): The newsletter's ID or slug ```bash curl -X POST "https://eu.flockstack.io/api/v1/newsletters/6650f1c2e9b1d4a012345678/welcome-test" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` ### Campaigns Drafts, test emails, scheduling, sending, sending in steps and reports. #### List campaigns `GET /api/v1/campaigns` · MCP tool `list_campaigns` · Full access · read-only, safe to repeat Lists campaigns, newest activity first: sent issues by send date, scheduled ones by send time, drafts by last edit. Content is left out; get_campaign has it. - `newsletter` (query, string): Only this newsletter's: its ID or slug. Default: every newsletter. - `status` (query, "draft" | "scheduled" | "sending" | "paused" | "sent"): Only campaigns with this status - `limit` (query, integer): How many, 50 by default, 200 at most ```bash curl "https://eu.flockstack.io/api/v1/campaigns?status=sent&limit=10" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Get a campaign `GET /api/v1/campaigns/{id}` · MCP tool `get_campaign` · Full access · read-only, safe to repeat Gets a campaign with its content, stats and, for drafts, what would block sending it now. - `id` (path, string, required): The campaign's ID ```bash curl "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Get a campaign's report `GET /api/v1/campaigns/{id}/report` · MCP tool `get_campaign_report` · Full access · read-only, safe to repeat Delivery, open, click, bounce, complaint and unsubscribe rates of a sent campaign, its list cleanup emails, results by inbox provider, and how many contacts a capped send hasn't reached yet. - `id` (path, string, required): The campaign's ID ```bash curl "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678/report" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Create a draft campaign `POST /api/v1/campaigns` · MCP tool `create_campaign` · Full access Creates a draft. Nothing is sent: review it in the dashboard or with get_campaign, then send_test_email, schedule_campaign or send_campaign. - `newsletter` (body, string): The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest. - `subject` (body, string): Subject line, 200 characters at most - `previewText` (body, string): Text inbox apps show after the subject, 300 characters at most - `format` (body, "markdown" | "rich" | "html"): markdown (the default when content is given), rich or html, as in update_campaign - `content` (body, string): The body in that format, 500 KB at most - `archiveSlug` (body, string): The issue's page path once sent. Default: made from the subject; a taken slug gets a number. - `audience` (body, "all" | "free" | "paid"): Who gets it: all active contacts (the default), only free readers, or only paid readers. free and paid need the newsletter's paid tier (set_paid_tier). A paid issue's web page shows a teaser; the full text is only in the email. - `segment` (body, string | null): A saved segment's ID or name: the campaign goes to its active contacts (within its audience) instead of all the newsletter's. null goes back to everyone. ```bash curl -X POST "https://eu.flockstack.io/api/v1/campaigns" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"subject":"This week","previewText":"Three links worth your time","content":"# This week\n\nThree links worth your time."}' ``` #### Update a draft campaign `PATCH /api/v1/campaigns/{id}` · MCP tool `update_campaign` · Full access · safe to repeat Changes a draft or scheduled campaign's subject, preview text, content, audience or segment. Send only the fields to change; format goes with content. Sent campaigns can't change. - `id` (path, string, required): The campaign's ID - `subject` (body, string): Subject line, 200 characters at most - `previewText` (body, string): Text inbox apps show after the subject, 300 characters at most - `format` (body, "markdown" | "rich" | "html"): With content: the format it's in. Default: the campaign's current format. - `content` (body, string): The body in that format, 500 KB at most - `audience` (body, "all" | "free" | "paid"): Who gets it: all active contacts (the default), only free readers, or only paid readers. free and paid need the newsletter's paid tier (set_paid_tier). A paid issue's web page shows a teaser; the full text is only in the email. - `segment` (body, string | null): A saved segment's ID or name: the campaign goes to its active contacts (within its audience) instead of all the newsletter's. null goes back to everyone. ```bash curl -X PATCH "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"subject":"This week, and one more link"}' ``` #### Delete a draft campaign `DELETE /api/v1/campaigns/{id}` · MCP tool `delete_campaign` · Full access · can't be undone, safe to repeat Deletes a draft or scheduled campaign: it leaves every list and a scheduled send never goes out. Sent campaigns can't be deleted. - `id` (path, string, required): The campaign's ID ```bash curl -X DELETE "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Duplicate a campaign `POST /api/v1/campaigns/{id}/duplicate` · MCP tool `duplicate_campaign` · Full access Copies a campaign's subject, preview text, content and segment into a new draft. - `id` (path, string, required): The campaign's ID ```bash curl -X POST "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678/duplicate" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Send a test email `POST /api/v1/campaigns/{id}/test` · MCP tool `send_test_email` · Full access · reaches outside FlockStack Sends the campaign as saved to the account owner's address, subject prefixed with [Test]. Nobody else gets it. It counts toward the plan's emails. - `id` (path, string, required): The campaign's ID ```bash curl -X POST "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678/test" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Schedule a campaign `POST /api/v1/campaigns/{id}/schedule` · MCP tool `schedule_campaign` · Full access · can't be undone, safe to repeat, reaches outside FlockStack Schedules a draft to send by itself at a time within a year. It goes out without asking again, unless unschedule_campaign runs first. Sending can't be undone: emails can't be recalled once they go out. Ask the user to confirm first. Plan limits and pre-send checks run now and again when it goes out. FlockStack Cloud paces a send by the volume its account has proven: its largest campaign of the last 60 days whose bounces and complaints stayed under the pause level, counted a day after it went out. A send, with what the account's other sends still have to send or sent in the last 24 hours, goes at full speed up to 200 emails, or that volume times 2 on the first day of the account's 30-day warm-up, rising to 5 by its last day and after it. A bigger send goes out over 4 hours plus 4 for each time it doubles that, 72 at most (spreadHours, sendingUntil); a resume keeps the pace, each step of send_campaign_to_more gets its own. Contacts never mailed before go in steps: a slice first, the rest 3 hours after it if the slice's bounces and complaints stay under the pause level. Past 2.00% hard bounces (at least 5) or 0.08% complaints (at least 2), the campaign pauses with pauseCode high_rates, or first_send_slice for a slice, and resume_campaign sends the rest. Past 5.00% (at least 10) or 0.30% (at least 3), the account is blocked. - `id` (path, string, required): The campaign's ID - `scheduledAt` (body, string, required): ISO 8601 date and time, e.g. 2026-10-20T09:00:00Z, at least a minute ahead - `audience` (body, "all" | "free" | "paid"): Who gets it: all, free or paid readers. Default: the campaign's own audience (see create_campaign). - `audienceLimit` (body, integer): Send to this many contacts at most, the most engaged first. The rest can follow with send_campaign_to_more. ```bash curl -X POST "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678/schedule" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"scheduledAt":"2026-10-20T09:00:00Z"}' ``` #### Cancel a scheduled send `POST /api/v1/campaigns/{id}/unschedule` · MCP tool `unschedule_campaign` · Full access · safe to repeat Turns a scheduled campaign back into a draft, so it doesn't go out. - `id` (path, string, required): The campaign's ID ```bash curl -X POST "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678/unschedule" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Send a campaign now `POST /api/v1/campaigns/{id}/send` · MCP tool `send_campaign` · Full access · can't be undone, reaches outside FlockStack Sends a draft or scheduled campaign now to the newsletter's active contacts, to the campaign's segment (update_campaign) or to its free or paid readers only (audience), most engaged first. Sending can't be undone: emails can't be recalled once they go out. Ask the user to confirm first. A campaign that is already sending or sent answers conflict, so a retry never sends twice. Plan limits, the from address, the postal address and the email size are checked first. FlockStack Cloud paces a send by the volume its account has proven: its largest campaign of the last 60 days whose bounces and complaints stayed under the pause level, counted a day after it went out. A send, with what the account's other sends still have to send or sent in the last 24 hours, goes at full speed up to 200 emails, or that volume times 2 on the first day of the account's 30-day warm-up, rising to 5 by its last day and after it. A bigger send goes out over 4 hours plus 4 for each time it doubles that, 72 at most (spreadHours, sendingUntil); a resume keeps the pace, each step of send_campaign_to_more gets its own. Contacts never mailed before go in steps: a slice first, the rest 3 hours after it if the slice's bounces and complaints stay under the pause level. Past 2.00% hard bounces (at least 5) or 0.08% complaints (at least 2), the campaign pauses with pauseCode high_rates, or first_send_slice for a slice, and resume_campaign sends the rest. Past 5.00% (at least 10) or 0.30% (at least 3), the account is blocked. - `id` (path, string, required): The campaign's ID - `audience` (body, "all" | "free" | "paid"): Who gets it: all, free or paid readers. Default: the campaign's own audience (see create_campaign). - `audienceLimit` (body, integer): Send to this many contacts at most, the most engaged first. The rest can follow with send_campaign_to_more. ```bash curl -X POST "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678/send" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Send a campaign to more contacts `POST /api/v1/campaigns/{id}/send-more` · MCP tool `send_campaign_to_more` · Full access · can't be undone, reaches outside FlockStack Sends a sent campaign to contacts who haven't received it yet, the next most engaged first: a send in steps. Sending can't be undone: emails can't be recalled once they go out. Ask the user to confirm first. Each call starts a new step, so check get_campaign_report before calling it again; while a step is still sending it answers conflict. FlockStack Cloud paces a send by the volume its account has proven: its largest campaign of the last 60 days whose bounces and complaints stayed under the pause level, counted a day after it went out. A send, with what the account's other sends still have to send or sent in the last 24 hours, goes at full speed up to 200 emails, or that volume times 2 on the first day of the account's 30-day warm-up, rising to 5 by its last day and after it. A bigger send goes out over 4 hours plus 4 for each time it doubles that, 72 at most (spreadHours, sendingUntil); a resume keeps the pace, each step of send_campaign_to_more gets its own. Contacts never mailed before go in steps: a slice first, the rest 3 hours after it if the slice's bounces and complaints stay under the pause level. Past 2.00% hard bounces (at least 5) or 0.08% complaints (at least 2), the campaign pauses with pauseCode high_rates, or first_send_slice for a slice, and resume_campaign sends the rest. Past 5.00% (at least 10) or 0.30% (at least 3), the account is blocked. - `id` (path, string, required): The campaign's ID - `additional` (body, integer): How many more contacts. Default: everyone who hasn't received it. ```bash curl -X POST "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678/send-more" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"additional":2000}' ``` #### Pause a campaign `POST /api/v1/campaigns/{id}/pause` · MCP tool `pause_campaign` · Full access · safe to repeat Stops a campaign that is sending. Emails already sent stay sent; the rest wait until resume_campaign. - `id` (path, string, required): The campaign's ID ```bash curl -X POST "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678/pause" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Resume a paused campaign `POST /api/v1/campaigns/{id}/resume` · MCP tool `resume_campaign` · Full access · can't be undone, reaches outside FlockStack Sends the rest of a paused campaign. Sending can't be undone: emails can't be recalled once they go out. Ask the user to confirm first. The plan limits and the account's state are checked again first. Resumed after a high_rates or first_send_slice pause, only the block level stops it again. - `id` (path, string, required): The campaign's ID ```bash curl -X POST "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678/resume" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Update a campaign's archive page `PATCH /api/v1/campaigns/{id}/archive` · MCP tool `update_campaign_archive` · Full access · safe to repeat Changes the path of a campaign's archive page (/p/), or pins a sent issue to the top of the archive. Works on sent campaigns too. - `id` (path, string, required): The campaign's ID - `slug` (body, string): Lowercase letters, digits and dashes. Empty removes it from a draft. - `pinned` (body, boolean): Pinned issues lead the archive ```bash curl -X PATCH "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678/archive" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"pinned":true}' ``` #### Preview the list cleanup of a send `GET /api/v1/campaigns/{id}/cleanup-preview` · MCP tool `preview_campaign_cleanup` · Full access · read-only, safe to repeat Counts what the newsletter's list cleanup would do if the campaign went out now: issues sent, last-chance emails instead, contacts still waiting to answer one, and contacts made dormant. Reads the whole list, so it can take a few seconds. - `id` (path, string, required): The campaign's ID - `audienceLimit` (query, integer): Count for a send capped at this many contacts - `includeRanks` (query, boolean): Also return, for each cold contact, how many issue recipients come before it, to recount any limit without asking again ```bash curl "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678/cleanup-preview" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Preview who a campaign goes to `GET /api/v1/campaigns/{id}/recipients` · MCP tool `preview_campaign_recipients` · Full access · read-only, safe to repeat Counts the contacts a send of the campaign would reach if it went out now, and shows the first few: the active contacts of its audience (all, free or paid) that are in its segment, or all the newsletter's, with suppressed addresses out. It also counts the emails it would use from the plan (the list cleanup's last-chance emails included) and whether they fit. Reads the whole list when the list cleanup is on, so it can take a few seconds. - `id` (path, string, required): The campaign's ID - `audienceLimit` (query, integer): Count for a send capped at this many contacts - `sample` (query, integer): How many of the most engaged recipients to list, 10 by default ```bash curl "https://eu.flockstack.io/api/v1/campaigns/6650f1c2e9b1d4a012345678/recipients" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` ### Contacts Search, signups, imports with checks, status changes, deletes and exports. #### List contacts `GET /api/v1/contacts` · MCP tool `list_contacts` · Full access · read-only, safe to repeat Lists contacts, newest signups first, 50 a page. Filter by newsletter, status, tag or the start of the email address; pass nextCursor back as cursor for the next page. counts has every status for the same filters. - `newsletter` (query, string): Only this newsletter's: its ID or slug. Default: every newsletter. - `status` (query, "active" | "pending" | "unsubscribed" | "bounced" | "complained" | "dormant"): Only contacts with this status - `tier` (query, "free" | "paid"): Only free or only paid contacts - `search` (query, string): Contacts whose email starts with this - `tag` (query, string): Only contacts with this tag - `limit` (query, integer): Contacts per page, 50 by default, 100 at most - `cursor` (query, string): nextCursor from the previous page ```bash curl "https://eu.flockstack.io/api/v1/contacts?status=active&search=jane" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Get a contact `GET /api/v1/contacts/{id}` · MCP tool `get_contact` · Full access · read-only, safe to repeat Gets one contact by ID or email address, with its status, dates and engagement. - `id` (path, string, required): The contact's ID or email address - `newsletter` (query, string): The newsletter's ID or slug, needed for an email address that is a contact of several newsletters ```bash curl "https://eu.flockstack.io/api/v1/contacts/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Add a contact `POST /api/v1/contacts` · MCP tool `add_contact` · Full access or signups only · reaches outside FlockStack Signs someone up, like the archive's form: they get the welcome email, or the confirmation email when the newsletter asks new subscribers to confirm. Signing up again keeps the contact as it is unless resubscribe is true, but its tags and fields are added to and set. Works with signups only keys, for website forms. Signups and confirmation emails keep coming in over the plan's limits; welcome emails count toward the month's emails and are skipped once they're used up, never sent later (get_billing's usage.welcomeEmailsPaused). A misspelled domain (gmial.com) answers validation_failed with the address it was likely meant to be; spam trap addresses, domains that can't receive email, and addresses FlockStack knows can't receive email (they hard bounced or hit a spam trap, from any sender on FlockStack) answer validation_failed too. - `newsletter` (body, string): The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest. - `email` (body, string, required): The subscriber's email address - `source` (body, string): Where they signed up, e.g. website. Default: api. - `resubscribe` (body, boolean): Bring back a contact who unsubscribed or went dormant. Bounced and complained addresses never come back, nor does a contact deleted after it unsubscribed. - `ip` (body, string): The visitor's IP address: one visitor gets 5 signups in 10 minutes - `referral` (body, string): The ref in the address the visitor arrived by, for a signup form of your own on a newsletter with a referral program: it credits the subscriber who shared the link, once this one confirms - `tags` (body, string[]): Tags to add: letters, digits, spaces and - _ . : / + &, 40 characters at most, lowercased - `fields` (body, object): Custom field values by field key, e.g. { "first_name": "Jane" }. null clears a value. The newsletter has to have the field (create_custom_field). ```bash curl -X POST "https://eu.flockstack.io/api/v1/contacts" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"email":"jane@example.com","source":"website"}' ``` #### Unsubscribe or reactivate a contact `PATCH /api/v1/contacts/{id}` · MCP tool `update_contact_status` · Full access · can't be undone, safe to repeat unsubscribed stops all emails to the contact, for good: only the person signing up again brings them back. active brings back a dormant contact; unsubscribes, bounces and complaints are final. - `id` (path, string, required): The contact's ID or email address - `newsletter` (body, string): The newsletter's ID or slug, needed for an email address that is a contact of several newsletters - `status` (body, "active" | "unsubscribed", required): active (dormant contacts only) or unsubscribed ```bash curl -X PATCH "https://eu.flockstack.io/api/v1/contacts/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"status":"unsubscribed"}' ``` #### Delete a contact `DELETE /api/v1/contacts/{id}` · MCP tool `delete_contact` · Full access · can't be undone, safe to repeat Deletes a contact from its newsletter, with its dates and engagement. It can't be undone. For a contact who unsubscribed, bounced or complained, FlockStack keeps a hash of the address so the newsletter never emails it again: import_contacts leaves it out, and add_contact or a signup form adds it back with that status. Any other contact can be added again like a new one. - `id` (path, string, required): The contact's ID or email address - `newsletter` (query, string): The newsletter's ID or slug, needed for an email address that is a contact of several newsletters ```bash curl -X DELETE "https://eu.flockstack.io/api/v1/contacts/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Import contacts `POST /api/v1/contacts/import` · MCP tool `import_contacts` · Full access · can't be undone, safe to repeat Adds up to 1000 contacts per call, with the same checks as the dashboard's CSV import: invalid, misspelled (gmial.com…), spam trap, role (info@, support@…), throwaway, duplicate and suppressed addresses, undeliverable ones (FlockStack knows they can't receive email: they hard bounced or hit a spam trap, from any sender on FlockStack), and addresses on domains that can't receive email, are left out and counted. consent must be true: "These people agreed to receive my emails". Existing contacts keep their status unless a row gives a stricter one (unsubscribed, bounced, complained), which is final. No welcome emails go out. Rows can carry tags and custom field values, and tags adds tags to every contact in the call. For more rows, send the next chunk with the importId of the first. - `newsletter` (body, string): The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest. - `consent` (body, boolean, required): Must be true: These people agreed to receive my emails. Bought or scraped lists aren't allowed. - `contacts` (body, object[], required): The rows, 1000 at most - `contacts[].email` (body, string, required): Invalid addresses are left out and counted - `contacts[].status` (body, "active" | "dormant" | "unsubscribed" | "bounced" | "complained"): active (default), dormant, unsubscribed, bounced or complained - `contacts[].subscribedAt` (body, string): When they signed up, ISO 8601 - `contacts[].emailsReceived` (body, number): Emails they got on the previous platform - `contacts[].openRate` (body, number): 0 to 1, from the previous platform: sends reach the most engaged first - `contacts[].clickRate` (body, number): 0 to 1, from the previous platform - `contacts[].tags` (body, string[]): Tags for this contact, added to the ones it has. Invalid tags are left out. - `contacts[].fields` (body, object): Custom field values by field key. Keys the newsletter has no field for and values that don't fit the field's type are left out. - `tags` (body, string[]): Tags added to every contact in the call, new or existing, e.g. the name of the list they came from - `importId` (body, string): The importId of the first chunk, to add rows to the same import - `duplicates` (body, integer): Duplicates you removed before sending, counted in the import's report ```bash curl -X POST "https://eu.flockstack.io/api/v1/contacts/import" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"consent":true,"contacts":[{"email":"jane@example.com","subscribedAt":"2025-03-01T00:00:00Z"},{"email":"sam@example.com","status":"unsubscribed"}]}' ``` #### Export contacts `GET /api/v1/contacts/export` · MCP tool `export_contacts` · Full access · read-only, safe to repeat Makes a CSV download link for the contacts matching the filters, valid for an hour, no API key needed to open it. The columns go back in through the import as they are. - `newsletter` (query, string): Only this newsletter's: its ID or slug. Default: every newsletter. - `status` (query, "active" | "pending" | "unsubscribed" | "bounced" | "complained" | "dormant"): Only contacts with this status - `search` (query, string): Contacts whose email starts with this - `tag` (query, string): Only contacts with this tag ```bash curl "https://eu.flockstack.io/api/v1/contacts/export?status=active" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` ### Referrals A referral program with rewards: settings, who referred whom, and the leaderboard. #### Get referral settings `GET /api/v1/referrals/settings` · MCP tool `get_referral_settings` · Full access · read-only, safe to repeat Gets a newsletter's referral program: whether it is on, its rewards, and how many referrals counted. Every subscriber has a link of their own to your website. A referral counts for the subscriber who shared it once the new subscriber confirms their address, and rewards unlock at the numbers you set. - `newsletter` (query, string): The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest. ```bash curl "https://eu.flockstack.io/api/v1/referrals/settings" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Update referral settings `PATCH /api/v1/referrals/settings` · MCP tool `update_referral_settings` · Full access · safe to repeat Turns a newsletter's referral program on or off and sets its rewards. Send only what changes; rewards replaces the whole list. A reward is a title, the number of referrals that unlocks it (1 to 10000) and a link or a message, revealed on the subscriber's referral page and sent in an email through the usual sending path, with its unsubscribe link, counted toward the month's emails. Up to 10 rewards. The program needs the newsletter's confirmation emails and website on: referral links lead to the website's signup form, and a referral counts once the new subscriber confirms. Put {{referral_link}} and {{referral_count}} in an issue to show each subscriber their link and count. - `newsletter` (body, string): The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest. - `enabled` (body, boolean): Turn the program on or off. Off keeps the counts and rewards. - `rewards` (body, object[]): The whole list of rewards - `rewards[].id` (body, string): The reward's ID, to keep its unlocks when you change it. Leave it out for a new reward. - `rewards[].referrals` (body, integer, required): Confirmed referrals that unlock it - `rewards[].title` (body, string, required): What the subscriber gets, 100 characters at most - `rewards[].url` (body, string): An https:// link revealed on unlock, e.g. a file or a page - `rewards[].text` (body, string): A message revealed on unlock, 1,000 characters at most ```bash curl -X PATCH "https://eu.flockstack.io/api/v1/referrals/settings" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"enabled":true,"rewards":[{"referrals":3,"title":"The field guide","url":"https://example.com/field-guide.pdf"}]}' ``` #### List referrals `GET /api/v1/referrals` · MCP tool `list_referrals` · Full access · read-only, safe to repeat Lists a newsletter's referrals, newest first, 50 a page: who referred whom, and whether it counted. A referral is pending until the new subscriber confirms, credited once it counts, and rejected when it never will: a self-referral, a repeat of one inbox or network, a flood, an address that can't be emailed. Pass nextCursor back as cursor for the next page. - `newsletter` (query, string): The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest. - `status` (query, "pending" | "credited" | "rejected"): Only referrals with this status - `referrer` (query, string): Only this subscriber's referrals: their contact ID - `limit` (query, integer): Referrals per page, 50 by default, 100 at most - `cursor` (query, string): nextCursor from the previous page ```bash curl "https://eu.flockstack.io/api/v1/referrals?status=rejected" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Get the referral leaderboard `GET /api/v1/referrals/leaderboard` · MCP tool `get_referral_leaderboard` · Full access · read-only, safe to repeat Lists the subscribers with the most confirmed referrals, most first, with how many each brought in. - `newsletter` (query, string): The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest. - `limit` (query, integer): How many subscribers, 25 by default, 100 at most ```bash curl "https://eu.flockstack.io/api/v1/referrals/leaderboard" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` ### Tags and fields Free-form tags on contacts, and custom fields (text, number, date) for merge tags, segments and automations. #### List tags `GET /api/v1/tags` · MCP tool `list_tags` · Full access · read-only, safe to repeat Lists the tags a newsletter's contacts have had, each with how many contacts have it now. Filter list_contacts or a segment by a tag. - `newsletter` (query, string): The newsletter's ID or slug. Default: the account's first newsletter. ```bash curl "https://eu.flockstack.io/api/v1/tags" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Add a tag to a contact `POST /api/v1/contacts/{id}/tags` · MCP tool `add_tag` · Full access · safe to repeat Gives a contact a tag, which segments can filter by and automations can start from (the tag added trigger). A contact has up to 30 tags and a newsletter up to 200. Adding a tag the contact has changes nothing. - `id` (path, string, required): The contact's ID or email address - `newsletter` (body, string): The newsletter's ID or slug, needed for an email address that is a contact of several newsletters - `tag` (body, string, required): The tag: letters, digits, spaces and - _ . : / + &, 40 characters at most. Tags are lowercased, so VIP and vip are one tag. ```bash curl -X POST "https://eu.flockstack.io/api/v1/contacts/6650f1c2e9b1d4a012345678/tags" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"tag":"vip"}' ``` #### Remove a tag from a contact `DELETE /api/v1/contacts/{id}/tags` · MCP tool `remove_tag` · Full access · safe to repeat Takes a tag off a contact. The tag stays on the newsletter's list of tags (delete_tag removes it everywhere). - `id` (path, string, required): The contact's ID or email address - `newsletter` (query, string): The newsletter's ID or slug, needed for an email address that is a contact of several newsletters - `tag` (query, string, required): The tag: letters, digits, spaces and - _ . : / + &, 40 characters at most. Tags are lowercased, so VIP and vip are one tag. ```bash curl -X DELETE "https://eu.flockstack.io/api/v1/contacts/6650f1c2e9b1d4a012345678/tags" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Delete a tag `DELETE /api/v1/tags` · MCP tool `delete_tag` · Full access · can't be undone, safe to repeat Takes a tag off every contact of the newsletter and forgets it. It can't be undone. Segments and automations that name the tag keep working but match nobody. - `newsletter` (query, string): The newsletter's ID or slug. Default: the account's first newsletter. - `tag` (query, string, required): The tag: letters, digits, spaces and - _ . : / + &, 40 characters at most. Tags are lowercased, so VIP and vip are one tag. ```bash curl -X DELETE "https://eu.flockstack.io/api/v1/tags" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### List custom fields `GET /api/v1/custom-fields` · MCP tool `list_custom_fields` · Full access · read-only, safe to repeat Lists a newsletter's custom fields: values like a first name, a plan or a renewal date that each contact can have. Merge tags ({{first_name|there}}), segments and automations use them. - `newsletter` (query, string): The newsletter's ID or slug. Default: the account's first newsletter. ```bash curl "https://eu.flockstack.io/api/v1/custom-fields" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Create a custom field `POST /api/v1/custom-fields` · MCP tool `create_custom_field` · Full access Adds a custom field to a newsletter, up to 20. Its type is text (500 characters), number or date (YYYY-MM-DD) and can't change later. Merge tags in campaigns name it by key: {{first_name}}, or {{first_name|there}} to print "there" for contacts without a value. - `newsletter` (body, string): The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest. - `label` (body, string, required): What the dashboard calls it, e.g. First name - `key` (body, string): Lowercase letters, digits and underscores, starting with a letter. Default: made from the label (first_name). - `type` (body, "text" | "number" | "date", required): text, number or date - `onSignupForm` (body, boolean): Ask for it on the newsletter's own signup form. Default: false. ```bash curl -X POST "https://eu.flockstack.io/api/v1/custom-fields" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"label":"First name","type":"text"}' ``` #### Update a custom field `PATCH /api/v1/custom-fields/{key}` · MCP tool `update_custom_field` · Full access · safe to repeat Changes a custom field's label, or whether the newsletter's signup form asks for it. Its key and type stay, since merge tags, segments and contacts' values use them. - `key` (path, string, required): The field's key, e.g. first_name - `newsletter` (body, string): The newsletter's ID or slug. Default: the account's first newsletter. - `label` (body, string): What the dashboard calls it - `onSignupForm` (body, boolean): Ask for it on the newsletter's own signup form ```bash curl -X PATCH "https://eu.flockstack.io/api/v1/custom-fields/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"label":"Given name"}' ``` #### Delete a custom field `DELETE /api/v1/custom-fields/{key}` · MCP tool `delete_custom_field` · Full access · can't be undone, safe to repeat Deletes a custom field and every contact's value for it. It can't be undone. Merge tags that name it print their fallback, and segments that use it match nobody. - `key` (path, string, required): The field's key, e.g. first_name - `newsletter` (query, string): The newsletter's ID or slug. Default: the account's first newsletter. ```bash curl -X DELETE "https://eu.flockstack.io/api/v1/custom-fields/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Set a contact's custom field `PATCH /api/v1/contacts/{id}/fields` · MCP tool `set_contact_field` · Full access · safe to repeat Sets one custom field of a contact, or clears it with a null value. The value has to fit the field's type: text, a number, or a date as YYYY-MM-DD. - `id` (path, string, required): The contact's ID or email address - `newsletter` (body, string): The newsletter's ID or slug, needed for an email address that is a contact of several newsletters - `field` (body, string, required): The field's key, e.g. first_name - `value` (body, string | number | null, required): The value, or null to clear it ```bash curl -X PATCH "https://eu.flockstack.io/api/v1/contacts/6650f1c2e9b1d4a012345678/fields" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"field":"first_name","value":"Jane"}' ``` ### Segments Saved audiences: rules over a newsletter's contacts, with live counts, that a campaign or an automation can use. #### List segments `GET /api/v1/segments` · MCP tool `list_segments` · Full access · read-only, safe to repeat Lists a newsletter's saved segments, each with its rules and live counts: how many contacts it matches now and how many of those are active. A segment is a saved audience: send a campaign to it (update_campaign's segment) or start an automation from it. - `newsletter` (query, string): The newsletter's ID or slug. Default: the account's first newsletter. ```bash curl "https://eu.flockstack.io/api/v1/segments" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Get a segment `GET /api/v1/segments/{id}` · MCP tool `get_segment` · Full access · read-only, safe to repeat Gets a segment with its rules, live counts and the newest contacts it matches. - `id` (path, string, required): The segment's ID ```bash curl "https://eu.flockstack.io/api/v1/segments/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Preview a segment `POST /api/v1/segments/preview` · MCP tool `preview_segment` · Full access · read-only, safe to repeat Counts the contacts some rules match, live, without saving them: send either rules or the ID or name of a saved segment. matching is every status, active the contacts that can get email, sendable those the account never suppressed. The list cleanup and the account's warm-up still apply when a campaign goes out (preview_campaign_recipients). - `newsletter` (body, string): The newsletter's ID or slug. Default: the account's first newsletter. - `segment` (body, string): A saved segment's ID or name, instead of rules - `rules` (body, object): Rules to count, instead of a saved segment - `rules.match` (body, "all" | "any", required): all: every condition (or group) has to hold. any: one is enough. - `rules.conditions` (body, object[], required): Conditions, or groups of conditions (a group has match and conditions and no type) - `sample` (body, integer): How many matching contacts to list, 10 by default ```bash curl -X POST "https://eu.flockstack.io/api/v1/segments/preview" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"rules":{"match":"all","conditions":[{"type":"tag","op":"has","value":"vip"}]}}' ``` #### Create a segment `POST /api/v1/segments` · MCP tool `create_segment` · Full access Saves rules as a segment, up to 50 a newsletter. Rules combine conditions with all (and) or any (or), and a condition can be a group with its own all or any, one level deep. Conditions: status, tag (has or has_not), field (a custom field compared with eq, neq, gt, gte, lt, lte, contains, starts_with, is_set, is_not_set), signup_date (from, to), source, engagement (opened, clicked, opened_or_clicked or dormant over days, or never_opened) and imported. Text comparisons are case sensitive. It follows the list: contacts are matched each time it's counted or sent to. - `newsletter` (body, string): The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest. - `name` (body, string, required): The segment's name, unique in the newsletter - `description` (body, string): What the segment is for, 300 characters at most - `rules` (body, object, required): The rules - `rules.match` (body, "all" | "any", required): all: every condition (or group) has to hold. any: one is enough. - `rules.conditions` (body, object[], required): Conditions, or groups of conditions (a group has match and conditions and no type) ```bash curl -X POST "https://eu.flockstack.io/api/v1/segments" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Engaged readers","rules":{"match":"all","conditions":[{"type":"engagement","kind":"opened_or_clicked","days":30}]}}' ``` #### Update a segment `PATCH /api/v1/segments/{id}` · MCP tool `update_segment` · Full access · safe to repeat Changes a segment's name, description or rules. Campaigns not yet sent and automations that use it follow the change; a campaign already sending keeps the audience it started with. - `id` (path, string, required): The segment's ID - `name` (body, string): The segment's name, unique in the newsletter - `description` (body, string | null): What the segment is for. null clears it. - `rules` (body, object): The new rules, which replace the old ones - `rules.match` (body, "all" | "any", required): all: every condition (or group) has to hold. any: one is enough. - `rules.conditions` (body, object[], required): Conditions, or groups of conditions (a group has match and conditions and no type) ```bash curl -X PATCH "https://eu.flockstack.io/api/v1/segments/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Engaged this month"}' ``` #### Delete a segment `DELETE /api/v1/segments/{id}` · MCP tool `delete_segment` · Full access · can't be undone, safe to repeat Deletes a saved segment. It can't be undone. A segment that a draft, scheduled or sending campaign, or an automation, still uses answers conflict: pick another audience for them first. Campaigns already sent keep the audience they went to. - `id` (path, string, required): The segment's ID ```bash curl -X DELETE "https://eu.flockstack.io/api/v1/segments/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` ### Automations Series of emails and actions that start for a contact when they subscribe, get a tag, join a segment or reach a date. #### List automations `GET /api/v1/automations` · MCP tool `list_automations` · Full access · read-only, safe to repeat Lists a newsletter's automations, newest first, each with its trigger, steps and how many contacts are in it, finished it or left it. An automation sends a series of emails and changes tags for each contact it starts for. - `newsletter` (query, string): The newsletter's ID or slug. Default: the account's first newsletter. - `status` (query, "draft" | "active" | "paused"): Only automations with this status ```bash curl "https://eu.flockstack.io/api/v1/automations" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Get an automation `GET /api/v1/automations/{id}` · MCP tool `get_automation` · Full access · read-only, safe to repeat Gets an automation with its trigger, its steps (emails with their content) and how many contacts are in it. - `id` (path, string, required): The automation's ID ```bash curl "https://eu.flockstack.io/api/v1/automations/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Create an automation `POST /api/v1/automations` · MCP tool `create_automation` · Full access Creates an automation as a draft: nothing is sent until activate_automation. A trigger starts it for a contact (they subscribe, get a tag, join a segment, or reach a date), and steps run in order: send an email, wait, add or remove a tag, or end. Up to 20 steps and 50 automations a newsletter. A contact enters an automation once. Emails go through the same checks as a campaign's: the account's plan emails, suppression and sending limits, with an unsubscribe link in each. - `newsletter` (body, string): The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest. - `name` (body, string, required): The automation's name, 100 characters at most - `trigger` (body, object, required): What starts the automation for a contact - `trigger.type` (body, "subscribed" | "tag_added" | "segment_joined" | "date_field", required): subscribed: a contact joins (confirmed, if the newsletter asks for it). tag_added: a contact gets the tag. segment_joined: a contact starts matching the segment, checked about every hour. date_field: the day of a contact's date field, plus offsetDays. - `trigger.tag` (body, string): tag_added: the tag. subscribed: only contacts who signed up with this tag. - `trigger.source` (body, string): subscribed: only contacts with this source, e.g. website or api - `trigger.segment` (body, string): segment_joined: the segment's ID or name - `trigger.field` (body, string): date_field: the key of a date custom field - `trigger.offsetDays` (body, integer): date_field: days after the date it starts, negative for before. Default 0. - `trigger.repeat` (body, "once" | "yearly"): date_field: once, or every year on that day (birthdays, anniversaries). Default once. - `trigger.includeExisting` (body, boolean): segment_joined: also start for the contacts already in the segment when it's activated. Default false: only the ones who join after. - `steps` (body, object[]): The steps, in order. Default: none yet. - `steps[].id` (body, string): A step's ID. Send the IDs you got back so contacts waiting on a step stay on it when the steps change. - `steps[].type` (body, "email" | "wait" | "add_tag" | "remove_tag" | "end", required): email: send an email. wait: wait. add_tag, remove_tag: change the contact's tags. end: the contact is done. - `steps[].subject` (body, string): email: the subject line, 200 characters at most - `steps[].previewText` (body, string): email: the text inbox apps show after the subject - `steps[].format` (body, "markdown" | "rich" | "html"): email: the format of content: markdown (the default), rich (an HTML fragment, what the dashboard editor writes) or html (a complete email) - `steps[].content` (body, string): email: the body in that format, 500 KB at most. Merge tags like {{first_name|there}} are filled in per contact. - `steps[].amount` (body, integer): wait: how many units - `steps[].unit` (body, "minutes" | "hours" | "days"): wait: minutes, hours or days - `steps[].tag` (body, string): add_tag, remove_tag: the tag ```bash curl -X POST "https://eu.flockstack.io/api/v1/automations" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Welcome series","trigger":{"type":"subscribed"},"steps":[{"type":"email","subject":"Welcome","content":"Thanks for joining, {{first_name|friend}}."},{"type":"wait","amount":2,"unit":"days"},{"type":"email","subject":"Where to start","content":"Here are three issues worth your time."}]}' ``` #### Update an automation `PATCH /api/v1/automations/{id}` · MCP tool `update_automation` · Full access · safe to repeat Changes an automation's name, trigger or steps. The trigger and steps of an active automation can't change: pause_automation first, then activate_automation again. Send all the steps, with the IDs you got back for the ones that stay, so contacts waiting on a step remain on it; a step without an ID is new. - `id` (path, string, required): The automation's ID - `name` (body, string): The automation's name, 100 characters at most - `trigger` (body, object): The new trigger - `trigger.type` (body, "subscribed" | "tag_added" | "segment_joined" | "date_field", required): subscribed: a contact joins (confirmed, if the newsletter asks for it). tag_added: a contact gets the tag. segment_joined: a contact starts matching the segment, checked about every hour. date_field: the day of a contact's date field, plus offsetDays. - `trigger.tag` (body, string): tag_added: the tag. subscribed: only contacts who signed up with this tag. - `trigger.source` (body, string): subscribed: only contacts with this source, e.g. website or api - `trigger.segment` (body, string): segment_joined: the segment's ID or name - `trigger.field` (body, string): date_field: the key of a date custom field - `trigger.offsetDays` (body, integer): date_field: days after the date it starts, negative for before. Default 0. - `trigger.repeat` (body, "once" | "yearly"): date_field: once, or every year on that day (birthdays, anniversaries). Default once. - `trigger.includeExisting` (body, boolean): segment_joined: also start for the contacts already in the segment when it's activated. Default false: only the ones who join after. - `steps` (body, object[]): All the steps, which replace the old ones - `steps[].id` (body, string): A step's ID. Send the IDs you got back so contacts waiting on a step stay on it when the steps change. - `steps[].type` (body, "email" | "wait" | "add_tag" | "remove_tag" | "end", required): email: send an email. wait: wait. add_tag, remove_tag: change the contact's tags. end: the contact is done. - `steps[].subject` (body, string): email: the subject line, 200 characters at most - `steps[].previewText` (body, string): email: the text inbox apps show after the subject - `steps[].format` (body, "markdown" | "rich" | "html"): email: the format of content: markdown (the default), rich (an HTML fragment, what the dashboard editor writes) or html (a complete email) - `steps[].content` (body, string): email: the body in that format, 500 KB at most. Merge tags like {{first_name|there}} are filled in per contact. - `steps[].amount` (body, integer): wait: how many units - `steps[].unit` (body, "minutes" | "hours" | "days"): wait: minutes, hours or days - `steps[].tag` (body, string): add_tag, remove_tag: the tag ```bash curl -X PATCH "https://eu.flockstack.io/api/v1/automations/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Welcome series, shorter"}' ``` #### Activate an automation `POST /api/v1/automations/{id}/activate` · MCP tool `activate_automation` · Full access · can't be undone, safe to repeat, reaches outside FlockStack Switches an automation on: from now on, contacts the trigger starts for get its emails without anyone asking again, until pause_automation. Sending can't be undone: emails can't be recalled once they go out. Ask the user to confirm first. The account's plan, from address, postal address and every email's size are checked first, and again as the emails go out. A segment trigger starts only the contacts who join the segment from now on, unless includeExisting is true. Contacts who unsubscribe, bounce or complain leave it. - `id` (path, string, required): The automation's ID ```bash curl -X POST "https://eu.flockstack.io/api/v1/automations/6650f1c2e9b1d4a012345678/activate" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Pause an automation `POST /api/v1/automations/{id}/pause` · MCP tool `pause_automation` · Full access · safe to repeat Stops an active automation: no new contacts enter and none move on, and no emails go out. Contacts in it continue where they were when it's activated again. - `id` (path, string, required): The automation's ID ```bash curl -X POST "https://eu.flockstack.io/api/v1/automations/6650f1c2e9b1d4a012345678/pause" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Delete an automation `DELETE /api/v1/automations/{id}` · MCP tool `delete_automation` · Full access · can't be undone, safe to repeat Deletes an automation: it leaves every list and the contacts in it are taken out, so nothing more is sent. It can't be undone. Emails already sent stay sent. - `id` (path, string, required): The automation's ID ```bash curl -X DELETE "https://eu.flockstack.io/api/v1/automations/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Get an automation's report `GET /api/v1/automations/{id}/report` · MCP tool `get_automation_report` · Full access · read-only, safe to repeat How an automation is doing: how many contacts entered, are in it, finished it or left it (and why), and for each step how many contacts wait to run it and, for emails, how many were sent, delivered, opened, clicked, bounced and complained. - `id` (path, string, required): The automation's ID ```bash curl "https://eu.flockstack.io/api/v1/automations/6650f1c2e9b1d4a012345678/report" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` ### Domains Own sending domains with their DNS records, and the shared address. #### List domains `GET /api/v1/domains` · MCP tool `list_domains` · Full access · read-only, safe to repeat Lists the account's own sending domains with their DNS records and status as last checked, and each newsletter's shared address (hello@.), which works with no setup. No parameters. ```bash curl "https://eu.flockstack.io/api/v1/domains" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Add a domain `POST /api/v1/domains` · MCP tool `add_domain` · Full access · reaches outside FlockStack Adds a domain to send from, in the account's own tenant at the email provider: emails are signed with DKIM and bounces return to a subdomain of it (rp. on PostShiba, bounce. on Amazon SES). The answer lists the DNS records to add; check_domain reads them once they're in. Newsletters can send from it once it's verified. - `domain` (body, string, required): e.g. example.com. An address or a link works too: jane@example.com and https://www.example.com/about both add example.com. - `archiveHost` (body, string): Used when the domain's setup lists an archive step: the subdomain for the archive, tracked links and unsubscribe links. Default: news.. ```bash curl -X POST "https://eu.flockstack.io/api/v1/domains" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"domain":"example.com"}' ``` #### Check a domain's DNS records `POST /api/v1/domains/{id}/check` · MCP tool `check_domain` · Full access · safe to repeat, reaches outside FlockStack Asks the email provider and DNS again whether the domain's records are in, and looks up its DMARC record or its parent domain's. On PostShiba, a check within a minute of the last one answers what that one found. When its setup lists an archive step, the newsletter sending from the domain moves its archive and links to that subdomain once it points at FlockStack. - `id` (path, string, required): The domain's ID ```bash curl -X POST "https://eu.flockstack.io/api/v1/domains/6650f1c2e9b1d4a012345678/check" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Remove a domain `DELETE /api/v1/domains/{id}` · MCP tool `remove_domain` · Full access · can't be undone, safe to repeat, reaches outside FlockStack Removes a domain from the email provider, and its archive subdomain from FlockStack when its setup lists one. Newsletters on it can't send until they move to another address. Refused while a campaign from it is sending, paused or scheduled. Adding it again needs new DNS records. - `id` (path, string, required): The domain's ID ```bash curl -X DELETE "https://eu.flockstack.io/api/v1/domains/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` ### Payments Whether the account can take payments, and connecting its Stripe account. FlockStack takes no cut of sales. #### Get the payments status `GET /api/v1/payments` · MCP tool `get_payments_status` · Full access · read-only, safe to repeat, reaches outside FlockStack Whether the account can take payments for products and paid subscriptions: on FlockStack Cloud, whether its connected Stripe account can take charges; on a self-hosted server, whether Stripe is set up. refresh asks Stripe for the account's latest status. FlockStack takes no cut of what you earn: your readers pay your own Stripe account, and only Stripe's own processing fee comes off. - `refresh` (query, boolean): Ask Stripe again, e.g. after the account owner finished onboarding. Default: false. ```bash curl "https://eu.flockstack.io/api/v1/payments?refresh=true" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Connect a Stripe account `POST /api/v1/payments/connect` · MCP tool `connect_payments` · Full access · reaches outside FlockStack Returns Stripe's own page where the account owner connects their Stripe account, or finishes connecting it: the account is created in their name, so they keep their money, refunds and disputes in their own Stripe dashboard. Nothing is connected until they finish there; get_payments_status shows when it is. Give the URL to the user. A self-hosted server answers conflict: it charges with its owner's own Stripe key. FlockStack takes no cut of what you earn: your readers pay your own Stripe account, and only Stripe's own processing fee comes off. No parameters. ```bash curl -X POST "https://eu.flockstack.io/api/v1/payments/connect" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` ### Paid subscriptions A newsletter's paid tier: prices, free trial and subscribers. Campaigns can go to paid readers only. #### Get a newsletter's paid tier `GET /api/v1/newsletters/{id}/paid-tier` · MCP tool `get_paid_tier` · Full access · read-only, safe to repeat Gets the paid tier of a newsletter: whether readers can subscribe, its prices, its free trial and how many paid subscribers it has. - `id` (path, string, required): The newsletter's ID or slug ```bash curl "https://eu.flockstack.io/api/v1/newsletters/6650f1c2e9b1d4a012345678/paid-tier" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Set a newsletter's paid tier `PATCH /api/v1/newsletters/{id}/paid-tier` · MCP tool `set_paid_tier` · Full access · safe to repeat Turns a newsletter's paid tier on or off and sets its prices. With it on, readers subscribe monthly or yearly on the newsletter's /subscribe page through Stripe Checkout, pay your own Stripe account, and become paid contacts: campaigns can then go to paid readers only (audience paid), with a teaser on the web and the full issue by email, and paid readers get a manage-subscription link in every email. Send only the fields to change. Prices apply to new subscribers; people already subscribed keep what they pay. Turning it off closes the page to new subscribers but doesn't cancel anyone: end subscriptions in Stripe. FlockStack takes no cut of what you earn: your readers pay your own Stripe account, and only Stripe's own processing fee comes off. - `id` (path, string, required): The newsletter's ID or slug - `enabled` (body, boolean): Open the paid tier to new subscribers. Needs a price and a Stripe account that can take payments (get_payments_status). - `monthlyCents` (body, integer): The price in the currency's smallest unit, e.g. 800 for $8.00; at least 100, or 0 to not offer the plan - `yearlyCents` (body, integer): The yearly price in the currency's smallest unit, e.g. 8000 for $80.00; at least 100, or 0 to not offer the plan - `currency` (body, "usd" | "eur" | "gbp" | "cad" | "aud" | "nzd" | "chf" | "sek" | "nok" | "dkk"): The currency of both prices: usd, eur, gbp, cad, aud, nzd, chf, sek, nok, dkk. Default: usd. - `trialDays` (body, integer): Free trial days before a new subscriber's first charge, 90 at most; 0 for none - `pitch` (body, string): A line or two on why to subscribe, shown on the subscribe page and the shop. 300 characters at most. ```bash curl -X PATCH "https://eu.flockstack.io/api/v1/newsletters/6650f1c2e9b1d4a012345678/paid-tier" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"enabled":true,"monthlyCents":800,"yearlyCents":8000,"trialDays":7}' ``` ### Products Digital products readers buy once: files kept private, pages on the newsletter's site, Stripe Checkout on your own account. #### Create a product `POST /api/v1/products` · MCP tool `create_product` · Full access Creates a digital product for one of the newsletter's readers to buy, as a draft: upload its file with set_product_file, then publish it with update_product (status active). It then has a page at /shop/ on the newsletter's site, and buyers pay through Stripe Checkout and get a download link by email. FlockStack takes no cut: the buyer pays your Stripe account, and only Stripe's own processing fee comes off. - `newsletter` (body, string): The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest. - `title` (body, string, required): The product's name, shown on its page and in Stripe's checkout, 120 characters at most - `description` (body, string): What the buyer gets, 2,000 characters at most - `priceCents` (body, integer, required): The price in the currency's smallest unit, e.g. 1900 for $19.00 (at least 100) - `currency` (body, "usd" | "eur" | "gbp" | "cad" | "aud" | "nzd" | "chf" | "sek" | "nok" | "dkk"): Default: usd - `slug` (body, string): The product page's path on the newsletter's site: /shop/. Default: made from the title. - `imageUrl` (body, string): A cover image: an https:// link, e.g. from upload_image. Empty removes it. ```bash curl -X POST "https://eu.flockstack.io/api/v1/products" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"title":"Launch checklist","priceCents":1900,"description":"A 12-page PDF of everything to do before you send your first issue."}' ``` #### Update a product `PATCH /api/v1/products/{id}` · MCP tool `update_product` · Full access · safe to repeat Changes a product's title, description, price, currency, slug or cover image, or puts it on sale (status active) or takes it back to a draft. Send only the fields to change. A price change applies to the next sale; earlier orders keep what they paid. Putting a product on sale needs its file and a Stripe account that can take payments (get_payments_status). FlockStack takes no cut: the buyer pays your Stripe account, and only Stripe's own processing fee comes off. - `id` (path, string, required): The product's ID - `title` (body, string): The product's name, shown on its page and in Stripe's checkout, 120 characters at most - `description` (body, string): What the buyer gets, 2,000 characters at most - `priceCents` (body, integer): The price in the currency's smallest unit, e.g. 1900 for $19.00 (at least 100) - `currency` (body, "usd" | "eur" | "gbp" | "cad" | "aud" | "nzd" | "chf" | "sek" | "nok" | "dkk"): The currency: usd, eur, gbp, cad, aud, nzd, chf, sek, nok, dkk - `slug` (body, string): The product page's path on the newsletter's site: /shop/. Default: made from the title. - `imageUrl` (body, string): A cover image: an https:// link, e.g. from upload_image. Empty removes it. - `status` (body, "draft" | "active"): active puts it on sale; draft takes it off sale without archiving it. Use archive_product to retire it. ```bash curl -X PATCH "https://eu.flockstack.io/api/v1/products/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"priceCents":2400,"status":"active"}' ``` #### List products `GET /api/v1/products` · MCP tool `list_products` · Full access · read-only, safe to repeat Lists the account's digital products, newest first, with how many each sold and what it earned. - `newsletter` (query, string): Only this newsletter's: its ID or slug. Default: every newsletter. - `status` (query, "draft" | "active" | "archived"): Only products with this status ```bash curl "https://eu.flockstack.io/api/v1/products?status=active" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Get a product `GET /api/v1/products/{id}` · MCP tool `get_product` · Full access · read-only, safe to repeat Gets one product with its file, its public page and what it sold. - `id` (path, string, required): The product's ID ```bash curl "https://eu.flockstack.io/api/v1/products/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Archive a product `POST /api/v1/products/{id}/archive` · MCP tool `archive_product` · Full access · safe to repeat Takes a product off sale and off the shop. Its earlier buyers keep their download links, and its orders stay. update_product with status draft brings it back. - `id` (path, string, required): The product's ID ```bash curl -X POST "https://eu.flockstack.io/api/v1/products/6650f1c2e9b1d4a012345678/archive" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Upload a product's file `POST /api/v1/products/{id}/file` · MCP tool `set_product_file` · Full access · reaches outside FlockStack Stores the file buyers download, up to 15 MB, sent as base64. It is kept in a private bucket and only ever served through a signed link that expires, never from a public URL. Replacing it changes what every buyer downloads from then on. - `id` (path, string, required): The product's ID - `base64` (body, string, required): The file, base64 encoded; a data: URL works too - `fileName` (body, string, required): The name buyers download it as, e.g. launch-checklist.pdf - `contentType` (body, string): The file's type, e.g. application/pdf. Default: application/octet-stream. ```bash curl -X POST "https://eu.flockstack.io/api/v1/products/6650f1c2e9b1d4a012345678/file" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"base64":"…","fileName":"…"}' ``` ### Orders What readers bought, who got their download link, and resending it. Refunds are made in Stripe. #### List orders `GET /api/v1/orders` · MCP tool `list_orders` · Full access · read-only, safe to repeat Lists the orders of the account's products, newest first, 50 a page: who bought, what they paid, whether the download email went out, and refunds. Pass nextCursor back as cursor for the next page. - `product` (query, string): Only this product's orders: its ID - `status` (query, "paid" | "refunded" | "disputed"): Only orders with this status - `limit` (query, integer): Orders per page, 50 by default, 100 at most - `cursor` (query, string): nextCursor from the previous page ```bash curl "https://eu.flockstack.io/api/v1/orders?status=paid&limit=20" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Get an order `GET /api/v1/orders/{id}` · MCP tool `get_order` · Full access · read-only, safe to repeat Gets one order: the buyer, the amount, refunds, how many times the file was downloaded and whether the download email went out. - `id` (path, string, required): The order's ID ```bash curl "https://eu.flockstack.io/api/v1/orders/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Resend an order's download link `POST /api/v1/orders/{id}/resend` · MCP tool `resend_order_email` · Full access · reaches outside FlockStack Emails the buyer a new download link, valid for 7 days. The earlier link stops working. Refunded and disputed orders can't be resent. Refunds are made in your Stripe dashboard. - `id` (path, string, required): The order's ID ```bash curl -X POST "https://eu.flockstack.io/api/v1/orders/6650f1c2e9b1d4a012345678/resend" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` ### Images Pictures for campaign content, on FlockStack's CDN, kept in the account's library to use again. #### List images `GET /api/v1/images` · MCP tool `list_images` · Full access · read-only, safe to repeat Lists the images uploaded to the account, newest first, 50 a page, so a campaign can use one again without uploading it twice. Pass nextCursor back as cursor for the next page. - `limit` (query, integer): Images per page, 50 by default, 100 at most - `cursor` (query, string): nextCursor from the previous page ```bash curl "https://eu.flockstack.io/api/v1/images?limit=20" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Upload an image `POST /api/v1/images` · MCP tool `upload_image` · Full access · reaches outside FlockStack Stores a PNG, JPEG, GIF or WebP image under 4 MB on FlockStack's CDN and returns its URL for campaign content. Send the file as base64 (under about 3 MB, since requests stop at 4.5 MB) or an https:// link FlockStack downloads. The URL never changes: sent emails keep pointing at it. list_images finds images uploaded before. - `base64` (body, string): The image file, base64 encoded; a data: URL works too - `url` (body, string): An https:// link to the image - `fileName` (body, string): Used in the stored file's name - `contentType` (body, string): The file's type, checked against its first bytes ```bash curl -X POST "https://eu.flockstack.io/api/v1/images" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url":"https://example.com/cover.png"}' ``` ### API keys Keys for the REST API and MCP. #### List API keys `GET /api/v1/api-keys` · MCP tool `list_api_keys` · Full access · read-only, safe to repeat Lists the account's API keys, revoked ones included, with their level and when they were last used. Keys themselves are never shown again. No parameters. ```bash curl "https://eu.flockstack.io/api/v1/api-keys" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Create an API key `POST /api/v1/api-keys` · MCP tool `create_api_key` · Full access Creates an API key and returns it once; only its hash is stored. full can do everything a full key can, including creating more keys; signups can only add contacts, for keys that end up in website code. An account has up to 20 active keys: one more answers conflict until one is revoked. - `name` (body, string, required): What the key is for, e.g. Website signups - `level` (body, "full" | "signups", required): full or signups ```bash curl -X POST "https://eu.flockstack.io/api/v1/api-keys" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Website signups","level":"signups"}' ``` #### Revoke an API key `DELETE /api/v1/api-keys/{id}` · MCP tool `revoke_api_key` · Full access · can't be undone, safe to repeat Revokes an API key for good: requests with it answer unauthorized from now on. A key can revoke itself. - `id` (path, string, required): The API key's ID ```bash curl -X DELETE "https://eu.flockstack.io/api/v1/api-keys/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### List connected apps `GET /api/v1/connected-apps` · MCP tool `list_connected_apps` · Full access · read-only, safe to repeat Lists the apps connected to the account with OAuth, such as ChatGPT, Claude and Grok Bot, with when they were connected and last used. Each one has full access, like a full access API key. No parameters. ```bash curl "https://eu.flockstack.io/api/v1/connected-apps" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Disconnect an app `DELETE /api/v1/connected-apps/{id}` · MCP tool `revoke_connected_app` · Full access · can't be undone, safe to repeat Disconnects an app connected with OAuth: its tokens stop working at once, and it has to ask for access again to come back. An app can disconnect itself. - `id` (path, string, required): The connected app's ID ```bash curl -X DELETE "https://eu.flockstack.io/api/v1/connected-apps/6650f1c2e9b1d4a012345678" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` ### Billing Plan, usage and links to Stripe to change plan. #### Get the plan and usage `GET /api/v1/billing` · MCP tool `get_billing` · Full access · read-only, safe to repeat The account's plan, subscription status and this month's usage against the plan's limits, with every plan on sale for comparison. Works without an active plan. A self-hosted server has no billing and answers billing_off. No parameters. ```bash curl "https://eu.flockstack.io/api/v1/billing" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Change plan `POST /api/v1/billing/change-plan` · MCP tool `change_plan` · Full access · reaches outside FlockStack Returns a billing page where the account owner picks up the change: Checkout without a paid plan (on a free plan too: the paid plan takes over), the Customer Portal with one (Stripe confirms the exact change there; Polar's portal lists the plans). Nothing changes until they confirm there. Give the URL to the user. A self-hosted server has no billing and answers billing_off. - `plan` (body, "starter" | "growth" | "pro" | "scale" | "max", required): starter, growth, pro, scale or max - `interval` (body, "month" | "year"): month (default) or year, which costs 10 months ```bash curl -X POST "https://eu.flockstack.io/api/v1/billing/change-plan" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"plan":"growth","interval":"year"}' ``` #### Open the billing portal `POST /api/v1/billing/portal` · MCP tool `open_billing_portal` · Full access · reaches outside FlockStack Returns a Customer Portal link (Stripe or Polar) for the account owner: payment method, invoices, plan changes and cancellation. A self-hosted server has no billing and answers billing_off. No parameters. ```bash curl -X POST "https://eu.flockstack.io/api/v1/billing/portal" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` ### Export Everything the account has in ZIP files: contacts, issues, images and settings. Never a paid feature. #### Export all account data `POST /api/v1/account/export` · MCP tool `export_account_data` · Full access · reaches outside FlockStack Starts an export of everything the account has, as ZIP files: every newsletter's contacts as a CSV (status, source, signup dates, engagement, tags), the suppression list, every issue and draft as Markdown and HTML with frontmatter (title, date, newsletter, archive address, status), the pictures they use, and a manifest.json that lists it all with each newsletter's settings. It is built in the background, which can take minutes for a large account; the account owner gets the download links by email, and get_account_export answers with them once status is ready. The links work for 7 days. Leaving is never a paid feature: it works for blocked accounts, paused ones and accounts without a plan. While an export is being made, calling this again answers that export with started false. No parameters. ```bash curl -X POST "https://eu.flockstack.io/api/v1/account/export" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ``` #### Get an account export `GET /api/v1/account/export` · MCP tool `get_account_export` · Full access · read-only, safe to repeat Gets an account export by ID, or the latest one: its status and, once it is ready, the download links. Works for blocked accounts and accounts without a plan. - `id` (query, string): The export's ID. Default: the latest one. ```bash curl "https://eu.flockstack.io/api/v1/account/export" \ -H "Authorization: Bearer $FLOCKSTACK_API_KEY" ```