MCP HeartbeatTHE MCP OBSERVATORY
Public workspace

Explore

Evidence for your next connection.

Independent measurements of remote MCP servers. Every observation has a timestamp.

Read-only probes

MCP server · Other

flayr

Create, schedule and publish social posts to 13 platforms for your brands.

Checks passed
12 / 22

2 failed · 8 not measured

Median response
1148 ms

Median of successful probes over 7 days

30-day uptime
Not measured

Share of countable probes over 30 days, including daily rollups. Auth challenges are excluded.

Discovered tools
135

Tool definitions returned by this server

Independent monitoring

Health & checks

Status history

Outdated check

Last connection measurement is over 24 hours old. Current availability is unknown.

Last checked
Check summary by test group
Test areaPassedFailedUnmeasured
ConnectionCan a client connect and discover tools?
500
Reliability & speedDoes it respond consistently and quickly?
004
Access & authenticationWhat is required to use this server?
102
Tool qualityAre the tool definitions usable by an agent?
310
Publisher identityCan the publisher be traced to its source?
312

Unmeasured means there is not enough evidence to decide. How these checks work

Inspect individual checks 22 recorded

Core

  • Pass
    Reachable

    Latest probe returned HTTP 200 in 1148 ms.

  • Pass
    Valid handshake

    protocolVersion 2025-11-25, serverInfo.name flayr.

  • Pass
    Lists tools

    tools/list returned 135 tools.

  • Pass
    Current protocol

    Negotiated 2025-11-25. The bar is 2025-06-18 or newer.

  • Pass
    HTTPS

    The endpoint URL is https.

Performance

  • Not measured
    Fast (p50)

    Median latency 1148 ms over 1 samples in 7 days. The bar is 1000 ms. Need at least 5 samples.

  • Not measured
    Consistent (p95)

    95th percentile 1148 ms over 1 samples in 7 days. The bar is 3000 ms. Need at least 20 samples.

  • Not measured
    Reliable (uptime)

    1 of 1 attempts returned a tool list in 30 days (100%). The bar is 99%. Need at least 30 samples.

  • Not measured
    Stable tool list

    Fewer than two successful probes in 30 days, so tool-list stability is not measured.

Access

  • Pass
    Open access

    tools/list succeeded with no credential, and the record declares none.

  • Not measured
    Standard auth

    Auth is not required, so the OAuth metadata check does not apply.

  • Not measured
    Free tier cited

    No publisher quote has been checked.

Tools

  • Pass
    Tools described

    Every tool description is at least 20 characters.

  • Pass
    Valid input schemas

    Every inputSchema is a JSON Schema object.

  • Fail
    Parameters documented

    411 of 790 parameters have a description (52%). The bar is 80%.

  • Pass
    Safety hints

    Every tool sets readOnlyHint or destructiveHint.

Publisher

  • Pass
    Verified namespace

    Listed in the Official MCP Registry.

  • Pass
    Website matches publisher

    The website host matches the reverse-domain namespace.

  • Fail
    Source repo linked

    No repository URL is on file.

  • Not measured
    Repo owner matches

    This namespace is not an io.github login, so the owner comparison does not apply.

  • Pass
    Recently updated

    Updated 2026-10-29T17:45:51.318424Z, within 180 days.

  • Not measured
    Open-source licence

    No GitHub repository to ask about a licence.

Start using flayr

Connect to this server

Choose your client, copy the configuration, then enable the server in your client’s MCP settings.

Run this command in your terminal, then restart Claude Code.

Claude Code

claude mcp add --transport http flayr https://flayr.social/api/mcp

Capabilities

Tools 135

Showing 100 of 135 tools.

account_refresh

[writes flayr data · `write` scope] Re-reads a connected account's handle, display name and avatar from the network (use after the user renames the account) and returns the stored values. Changes nothing else: no connect, disconnect or post. If the status is not `updated`, tell the user to reconnect the account at the returned `reconnectUrl`. (Wraps POST /api/v2/accounts/{id}/refresh.)

Discovered
act_on_publish_action

[PUBLISHES to social accounts · `publish` scope] approve lets a rule's reshare / comment go out at its time; retry re-sends a failed one (same idempotency key); reject / cancel stop it. Confirm with the user before approving. Needs the `publish` scope (or admin) on the Agency plan or higher. (Wraps POST /api/v2/automations/actions/{id}.)

Discovered
ad_cut_lint

[writes flayr data · `write` scope] Checks an ad's cut against the ad-cut rules: too many joins (warning), joins only at a rest point, no cut inside a caption or its fade, one caption layer, no audio dip at a join, exactly one ending, and the network's length / aspect / ad-text window (TikTok 9:16, 12-25 s, ad text up to 100 by default). Each finding names its fix. It reads the cut you describe (segments, captions, signals), not a rendered file; a rule with nothing to check is reported unchecked. With contentId the result is kept for that draft: a format:ad video draft is booked or filed as an ad only once its latest lint for the network passes. (Wraps POST /api/v2/video-studio/ad-cut/lint.)

Discovered
add_post_comments

[PUBLISHES to social accounts · `publish` scope] Schedules comments on a post, sent once after it is live on that platform and its tokens resolve ({{postUrl}}, {{parentPostUrl:<post id>}}, {{youtubeUrl:<post id>}}), optionally at sendAt. Confirm with the user first. Needs the `publish` scope (or admin) on the Agency plan or higher. (Wraps POST /api/v2/posts/{id}/comments.)

Discovered
add_queue_items

[PUBLISHES to social accounts · `publish` scope] Appends drafts (content ids) to the end of a queue — they will be BOOKED AND POSTED on the queue's schedule. Use `contentIds`, or `items` for a per-item YouTube title or platforms. Drafts of another brand, duplicates, archived drafts and drafts without a video for a video platform come back in `rejected`. Needs the `publish` scope (or admin) on the Agency plan or higher. (Wraps POST /api/v2/queues/{id}/items.)

Discovered
ads_account_spend_limit_set

[writes · `ads:spend` scope] Sets the Meta ad account spending limit, in the account currency (e.g. 800 = $800). Removing the limit (null) always needs the owner. Inside the owner's agent ceiling it is applied at once; above it the result is `approval_requested`: tell the user the owner has an approval request in Ads > Agent activity, and repeat the same call once they approve. Pass agentName and reason; both are shown to the owner. (Wraps POST /api/v2/ads/accounts/spend-limit.)

Discovered
ads_accounts_list

[read-only] The brand's ad account with its currency, spend limit, balance (minor units) and readiness. (Wraps GET /api/v2/ads/accounts.)

Discovered
ads_ad_set_dataset

[writes · `ads:manage` scope] Attaches a Meta dataset (pixel) to an existing ad set, optionally with the conversion event (e.g. PURCHASE). Pass agentName and reason. Audited in Ads > Agent activity. It cannot be undone from there: to change it back, call this tool again with the earlier settings. (Wraps POST /api/v2/ads/ad-sets/{id}/dataset.)

Discovered
ads_ad_set_placements

[writes · `ads:manage` scope] Changes where an existing ad set runs. `excludeAudienceNetwork: true` keeps Facebook, Instagram and Messenger and drops Audience Network; or pass an explicit publisherPlatforms list. `id` is the ad set id from ads_campaign_get. Pass agentName and reason. Audited in Ads > Agent activity. It cannot be undone from there: to change it back, call this tool again with the earlier settings. (Wraps POST /api/v2/ads/ad-sets/{id}/placements.)

Discovered
ads_agent_activity

[read-only] Recent agent actions on ads (agent name, reason, outcome), owner approval requests still pending, and the owner's agent ceilings. Use it to see whether an approval request was decided. (Wraps GET /api/v2/ads/agent/activity.)

Discovered
ads_boost_candidates

[read-only] The brand's published posts ranked for a boost (reach, engagement rate, link clicks, recency), with score parts, the call-to-action link found, and whether an ad account is connected for the network. Removed posts, posts with no call to action and networks a boost can't run on are left out. Read-only: nothing is boosted or charged. (Wraps GET /api/v2/ads/boost-candidates.)

Discovered
ads_campaign_approve

[writes · `ads:manage` scope] Approves a proposed ad campaign. With activate: true it also switches it on (needs ads:spend too), through the normal activation checks, when its daily budget is within the owner's agent activation ceiling. Inside the owner's agent ceiling it is applied at once; above it the result is `approval_requested`: tell the user the owner has an approval request in Ads > Agent activity, and repeat the same call once they approve. Pass agentName and reason; both are shown to the owner. Confirm with the user before activating. (Wraps POST /api/v2/ads/campaigns/{id}/approve.)

Discovered
ads_campaign_create

[writes · `ads:manage` scope] Creates a Meta Instant Form lead campaign (goal lead_generation, the ad set's leadGenFormId from ads_lead_forms_list, placements without Audience Network, the age range and countries in targeting) with one image ad, created PAUSED. It lands in the owner's Proposed campaigns and never runs or spends until the owner approves it (ads_campaign_approve). headline, body, imageUrl or creativeId and budget (dollars; budgetType daily or lifetime) are required; promotedObject.pageId picks the Facebook Page. Pass agentName and reason. Audited in Ads > Agent activity. (Wraps POST /api/v2/ads/campaigns.)

Discovered
ads_campaign_get

[read-only] One ad campaign by its Flayr id, with its ad sets and ads, including each ad's network review status, reason when available, and last sync time. Do not invent a rejection reason when the network supplies none. (Wraps GET /api/v2/ads/campaigns/{id}.)

Discovered
ads_campaign_pause

[writes flayr data · `write` scope] Pauses a live ad campaign on its ad network so it stops spending (`action: "pause"` or `"stop"`; both leave it paused). To approve and switch on a proposed campaign use ads_campaign_approve. Confirm with the user first. (Wraps POST /api/v2/ads/campaigns/{id}/pause.)

Discovered
ads_campaigns_list

[read-only] The brand's ad campaigns with status, budget, start/end dates, max spend, spend to date, ad sets and ads. Filter by status or platform. (Wraps GET /api/v2/ads/campaigns.)

Discovered
ads_caps_set

[writes · `ads:spend` scope] Sets the brand's monthly and/or per-campaign activation caps, in cents (e.g. 50000 = $500). Inside the owner's agent ceiling it is applied at once; above it the result is `approval_requested`: tell the user the owner has an approval request in Ads > Agent activity, and repeat the same call once they approve. Pass agentName and reason; both are shown to the owner. (Wraps POST /api/v2/ads/caps.)

Discovered
ads_deep_dive_compare

[read-only] Compare an older and a newer saved run: each finding is new, resolved, worse, better or unchanged, with metric deltas. (Wraps GET /api/v2/ads/deep-dives/compare.)

Discovered
ads_deep_dive_get

[read-only] One saved deep dive by id, as json or an export (markdown, csv, pdf) of the stored report. List recent runs with GET /api/v2/ads/deep-dives. (Wraps GET /api/v2/ads/deep-dives/{id}.)

Discovered
ads_deep_dive_quote

[read-only] The Embers price of a deep dive on a saved snapshot, and whether a recent run makes it free. Charges nothing. Ask the owner before running. (Wraps GET /api/v2/ads/deep-dives/quote.)

Discovered
ads_deep_dive_run

[writes flayr data · `write` scope] Run a deep dive on a saved snapshot and save the report. Charges Embers only when confirmEmbers equals the current quote total; a failed run is refunded. Changes no ad, budget or campaign. (Wraps POST /api/v2/ads/deep-dives.)

Discovered
ads_insights

[read-only] Impressions, clicks, spend, link clicks and leads per campaign for a date range (default the last 30 days, at most 93), with totals per currency. Pass `level: "ad"` for daily per-ad results summed per ad (spend, impressions, clicks, CTR, video views), each with the Library `contentId` the ad was built from (null when unlinked; `unlinked` counts those). (Wraps GET /api/v2/ads/insights.)

Discovered
ads_lead_form_create

[writes · `ads:manage` scope] Creates a Meta Instant Form on the brand's selected ad account: name, privacyPolicyUrl (https), questions (Meta question objects, e.g. { type: "EMAIL" }, { type: "FULL_NAME" }, or a CUSTOM question with label and options), optional contextCard, thankYou* fields and followUpActionUrl (same fields as the dashboard form). Same builder and limits as the dashboard. One vendor call, never retried; pass idempotencyKey to make repeats safe. Pass agentName and reason. Audited in Ads > Agent activity. (Wraps POST /api/v2/ads/lead-forms.)

Discovered
ads_lead_forms_list

[read-only] The Meta Instant Forms (lead forms) on the brand's selected ad account: id, name, status. Use a form id as leadGenFormId in ads_campaign_create. (Wraps GET /api/v2/ads/lead-forms.)

Discovered
ads_offer_update

[writes flayr data · `write` scope] Records the claim of one offer row (`claimId` = a row id from ads_offers_list): status, the date it was claimed, and notes. Owners and admins of the brand only. A record only: it never creates, turns on or funds an ad. (Wraps PATCH /api/v2/ads/offers/{claimId}.)

Discovered
ads_offers_list

[read-only] The brand's new-advertiser offers per ad network, one row per ad account (or a network not connected yet): status, spend so far, what is left to spend, the daily pace and the deadline, and how to claim. Read-only. (Wraps GET /api/v2/ads/offers.)

Discovered
ads_readiness

[read-only] Whether each connected network and ad account can run ads, and what to fix first. (Wraps GET /api/v2/ads/readiness.)

Discovered
ads_snapshot_collect

[writes flayr data · `write` scope] Save an immutable, org and brand scoped snapshot for selected ad accounts and an inclusive 1–30 day window. Reads vendors only; no charge, analysis, ad writes or spend. Each source reports availability. (Wraps POST /api/v2/ads/snapshots.)

Discovered
ads_snapshots_get

[read-only] Read one saved ads data snapshot by id, or recent snapshot headers for the active brand. No cross-org access. (Wraps GET /api/v2/ads/snapshots.)

Discovered
apply_frame

[writes flayr data · `write` scope] Draws a frame over an image and returns a new image URL (the original is untouched). Use the URL in create_content, or pass contentId + platform so that post publishes the framed image on that platform. Free by default; the same inputs again are free. (Wraps POST /api/v2/frames/apply.)

Discovered
archive_content

[writes flayr data · `write` scope] Soft-archives an uncommitted draft or failed generation. Keeps its content and media; Restore is available in the Library Archive view. Repeating the call is safe. Refused (409) for ready, staged, scheduled or published content, or any posting queue, post or approval history. Needs write scope and the same owner/admin authority as Library archive. A brand-bound connection only reaches its own brand. (Wraps POST /api/v2/content/{id}/archive.)

Discovered
bodies_map

[writes flayr data · `write` scope] Maps library clips, Shopify products, features or texts to draft bodies (what each shows and proves) so hooks can lead into them. Charges Embers once per call (refunded when nothing usable comes back). Needs the Pro plan or higher. (Wraps POST /api/v2/hook-studio/bodies/map.)

Discovered
brand_business_details_get

[read-only] A brand's legal name, registered address, website, currency and timezone: what ad networks ask for when you open an ads account. `hasTaxId` says whether a tax id is on file; the tax id itself is never returned. Use an `id` from list_brands. (Wraps GET /api/v2/brands/{id}/business-details.)

Discovered
brand_business_details_update

[writes flayr data · `write` scope] Sets a brand's legal name, registered address, currency (ISO, like USD) and/or timezone (IANA, like America/New_York). Only the fields sent change; a brand with no details yet needs all four. Do not send a tax id: it is refused. A brand owner or admin adds it in flayr (Brand › Overview). (Wraps PATCH /api/v2/brands/{id}/business-details.)

Discovered
brand_profile_get

[read-only] A brand's profile (website, companyName, tagline, industry, audience, values, pillars, hashtag sets), its default voice, colors and fonts. `brandId` comes from list_brands; a brand-bound connection may omit it. (Wraps GET /api/v2/brand/intelligence.)

Discovered
brand_profile_update

[writes flayr data · `write` scope] Fills in a brand's profile — e.g. `{ brandId, profile: { website: "https://…" } }`. Changes only the fields you send; the voice, colors and fonts stay as they are unless you pass them. Use it to clear list_brands setup items such as hasWebsite. Owners, admins and editors only; every change is audited against this connection. (Wraps PATCH /api/v2/brand/intelligence.)

Discovered
cancel_scheduled_post

[PUBLISHES to social accounts · `publish` scope] Takes a SCHEDULED post off the platform schedule and marks it cancelled (the draft stays, so it can be published again). Safe to repeat. Refused within 5 minutes of the slot, and when the platform will not remove it (some YouTube uploads). Needs the `publish` scope (or admin) and the Pro plan or higher; each publish counts against the plan's direct posts for the month. Confirm with the user first. (Wraps DELETE /api/v2/posts/{id}.)

Discovered
claims_check

[read-only] Checks a hook, CTA, caption or ad against the brand's claims sources (verified prices, banned phrases, competitors, destinations). No model call, nothing stored, free. Needs the Pro plan or higher. (Wraps POST /api/v2/hook-studio/claims/check.)

Discovered
close_experiment_round

[writes flayr data · `write` scope] Freezes the open round's numbers and keeps the best arms for the next round. A winner is recorded only when the readout says likely_winner, or when `pick` names an arm the user chose. Ask the user before passing `pick`. (Wraps POST /api/v2/experiments/{id}/close-round.)

Discovered
combine_clips

[writes flayr data · `write` scope] Extends a video draft (`id`) with more clips and image cards into ONE finished video, rendered by flayr and saved as a NEW linked draft (same brand, caption copied, credits merged, labelled variant:combined). Nothing is posted and the original is unchanged. Use it to show a finished print with painting/assembly clips before or after it. `segments` (2-8, in order) must include the video itself as { kind: "clip", contentId: id }; clips are Library videos (contentId) or uploads (storageId from upload_media) with inMs/outMs (or durationMs = the clip's full length); cards are images (contentId of a Library image or video thumbnail, or imageStorageId) with durationMs and optional text. `transition` cut|crossfade, `audio` keep|mute_extras|main_across. Max 60 min by default (long-form: cold open + trimmed recording + bumpers). Costs 25 Embers per started minute of output for the first 3 min, then 5 per further started minute by default (refunded on failure). Returns a jobId — poll get_job_status. (Wraps POST /api/v2/content/{id}/combine.)

Discovered
compare_labels

[read-only] Splits every labelled post by the values of one label key (e.g. key "cut" → cut:opus vs cut:raw) and reports medians with n per group at the 48h / 7d snapshot. Descriptive, not a significance test. Pro plan or higher. (Wraps GET /api/v2/analytics/experiments.)

Discovered
compare_post_instances

[read-only] Per-account metrics and tag, campaign, experiment and series roll-ups. Omit postId for scope-wide roll-ups (up to 100 posts). Include reruns to compare bookings of the same content over time. Historical data stays platform-attributed. Pro plan or higher. (Wraps GET /api/v2/analytics/instances.)

Discovered
create_content

[writes flayr data · `write` scope] Creates a DRAFT content item. Nothing is posted. Give `text` plus optional media (`videoUrl` / `imageUrl`, or `videoStorageId` / `imageStorageId` from upload_media), target `platforms`, `brandId` (from list_brands; omitted → the brand last active in the dashboard), per-platform captions (`platformText`), creator `credits`, `labels` and YouTube options. Returns the new `id` — pass it as `contentId` to publish or add_queue_items. (Wraps POST /api/v2/content.)

Discovered
create_experiment

[writes flayr data · `write` scope] Creates an A/B experiment. Then tag drafts with its `label` (experiment:<id>) and `<compareKey>:<variant>` via update_content `labels`, publish them, and read get_experiment_results. (Wraps POST /api/v2/experiments.)

Discovered
create_frame

[writes flayr data · `write` scope] Copy a flayr frame into the brand library (`defaultKey`, optional colors/texts), or add uploaded PNG/SVG art (upload_media first; `variants` of storageIds, the content area is detected from transparency). (Wraps POST /api/v2/frames.)

Discovered
create_growth_trigger

[writes flayr data · `write` scope] Creates a keyword trigger, always INACTIVE: nothing is sent until a person turns it on. DMs work on Instagram and Facebook only; the reply text must not contain a keyword. (Wraps POST /api/v2/growth-triggers.)

Discovered
create_queue

[PUBLISHES to social accounts · `publish` scope] Creates a posting queue. Once items are added it BOOKS REAL POSTS on the given platforms on its cadence (default daily 19:00 America/Chicago, 2 booked ahead). Use `startsAt` to hold everything until a date. Needs the `publish` scope (or admin) on the Agency plan or higher. (Wraps POST /api/v2/queues.)

Discovered
create_share_rule

[PUBLISHES to social accounts · `publish` scope] Creates a rule that reshares (or comments on) every new post of the source accounts. Defaults to needs_approval: each fire waits for approve in act_on_publish_action. Only LinkedIn (native reshare) and X (quote own / retweet) really repost; other platforms get a link share. Confirm with the user first. Needs the `publish` scope (or admin) on the Agency plan or higher. (Wraps POST /api/v2/automations/reshare-rules.)

Discovered
create_text_template

[writes flayr data · `write` scope] Creates a reusable format (text template) in a brand. (Wraps POST /api/v2/text-templates.)

Discovered
cta_check

[read-only] Checks whether a draft, post or link points at the brand's goal page (the same check the ad and boost routes run in paid mode; a block there refuses the ad). Run it before every boost or ad and paste the result. Nothing stored, free. Needs the Pro plan or higher. (Wraps POST /api/v2/cta-check.)

Discovered
cta_settings_get

[read-only] The brand's goals (source tagged, implicit from the website, or none; the primary goal) and its CTA check settings (ctaLevel, ctaPaidLevel, organicSupportingHosts, autoApplyPrimaryCta). Free. Needs the Pro plan or higher. (Wraps GET /api/v2/hook-studio/cta-settings.)

Discovered
cta_settings_update

[writes flayr data · `write` scope] Changes only the CTA check settings sent: ctaLevel (off, warn, block), ctaPaidLevel (warn or block), organicSupportingHosts and autoApplyPrimaryCta. Only the brand's owners and admins can change them. Confirm changes with the person first. Free. Needs the Pro plan or higher. (Wraps PATCH /api/v2/hook-studio/cta-settings.)

Discovered
ctas_create

[writes flayr data · `write` scope] Adds a call to action written by the person, claims-checked, optionally tagged as a goal (goalKey; isPrimary makes it the brand's primary goal and demotes the previous one). Nothing here creates or runs an ad. Free. Needs the Pro plan or higher. (Wraps POST /api/v2/hook-studio/ctas.)

Discovered
ctas_generate

[writes flayr data · `write` scope] Writes a batch of draft calls to action for the confirmed offers, claims-checked against where they point. Charges Embers once per call (refunded when nothing usable comes back). Needs the Pro plan or higher. (Wraps POST /api/v2/hook-studio/ctas/generate.)

Discovered
ctas_list

[read-only] The brand's CTA bank (filter by status: draft, approved, retired), with each CTA's goal (goalKey, isPrimary, paidEligible, adButton) and claims result. Free. Needs the Pro plan or higher. (Wraps GET /api/v2/hook-studio/ctas.)

Discovered
ctas_update

[writes flayr data · `write` scope] Edits a CTA, its status or its goal fields (goalKey, isPrimary, paidEligible, adButton). New copy or a new destination is claims-checked again; a CTA whose claims block cannot be approved. Free. Needs the Pro plan or higher. (Wraps PATCH /api/v2/hook-studio/ctas.)

Discovered
decide_approval

[PUBLISHES to social accounts · `publish` scope] Same rules as the dashboard: the assigned approver, or an owner/admin of the org, may decide. On a "workflow" approval, decision "approve" resumes the parked run, whose next steps may publish (GOES LIVE); "reject" cancels it. On a "manual" approval, "approve" only marks the content approved — nothing is posted until you call publish with its contentId — and "reject" returns it to draft. On "reject", pass the reviewer's reason as `note` (the submitter is told it); it is optional unless the org requires one (then 422 without it). Needs the explicit `approve` scope (admin does not include it). Agency plan. Repeating the same decision is safe (alreadyDecided: true). Confirm with the user before approving a workflow approval. (Wraps POST /api/v2/approvals/{id}.)

Discovered
decide_approval_group

[PUBLISHES to social accounts · `publish` scope] Decides several variants of a group from list_approval_groups at once, each as decide_approval would: `members` "all" (open variants), an array of approvalIds, or {axis: value} (e.g. {"audio":"voice"}). "approve" marks them approved (a manual approval is NOT posted; a workflow approval resumes its run, which may publish — GOES LIVE); "redo" rejects with the Redo reason; "drop" rejects (`note` = reason). Already-decided variants are skipped. Needs the explicit `approve` scope (admin does not include it). Agency plan. Confirm the count with the user first. (Wraps POST /api/v2/approval-groups/{groupId}/decide.)

Discovered
decide_campaign_review_section

[PUBLISHES to social accounts · `publish` scope] action "approve" approves the section's pending pieces (or pieceIds) and their held posts GO LIVE at their slots — needs the explicit `review` scope (admin does not include it); QA-failed pieces are skipped unless overrideQa. "fix" sends the pieces back with a `note` (required): their posts are taken off the schedule and the section opens a new round; other sections are untouched. "drop" takes the posts off the schedule and drops the pieces. "ready" puts fixed pieces back up for review. fix/drop/ready need `review` or `publish`. Agency plan. Confirm with the user first. (Wraps POST /api/v2/campaigns/{id}/review/sections/{sectionId}.)

Discovered
decide_review

[PUBLISHES to social accounts · `publish` scope] decision "approve" sends a held post to the platform for its slot (GOES LIVE) — needs the explicit `review` scope (admin does not include it) and never works on a post the same connection created. decision "hold" takes a scheduled post off the platform schedule — needs `review` or `publish`. Agency plan. `id` is a reviewId or a convexPostId. (Wraps POST /api/v2/reviews/{id}.)

Discovered
delete_content

[DESTRUCTIVE] DESTRUCTIVE: permanently deletes a content item from the library. Posts already live on a platform are not removed. Needs the `write` scope. Ask the user before calling. (Wraps DELETE /api/v2/content/{id}.)

Discovered
delete_experiment

[DESTRUCTIVE] DESTRUCTIVE: deletes the experiment record (content keeps its labels). Ask the user before calling. (Wraps DELETE /api/v2/experiments/{id}.)

Discovered
delete_growth_trigger

[DESTRUCTIVE] DESTRUCTIVE: deletes a trigger (its logs stay). Ask the user before calling. (Wraps DELETE /api/v2/growth-triggers/{id}.)

Discovered
delete_queue

[DESTRUCTIVE] DESTRUCTIVE: deletes the queue (its drafts stay in the library). With posts booked at the platform it is refused (409) unless `unschedule: true`, which first deletes those platform posts. Needs the `publish` scope (or admin) on the Agency plan or higher. Ask the user before calling. (Wraps DELETE /api/v2/queues/{id}.)

Discovered
delete_text_template

[DESTRUCTIVE] DESTRUCTIVE: deletes a format (drafts started from it keep their text). Ask the user before calling. (Wraps DELETE /api/v2/text-templates/{id}.)

Discovered
edit_post_labels

[writes flayr data · `write` scope] Sets internal post labels and per-platform/account instanceLabels. Omitted sets stay unchanged; [] clears a set; labelMode set replaces both sets, add appends atomically. Use get_post to list both. Works after booking and publishing, and never contacts social networks. Labels are key:value (campaign, experiment, variant, repost, series, source-run, or free keys). Needs publish scope and the publishing plan. (Wraps PATCH /api/v2/posts/{id}.)

Discovered
get_analytics

[read-only] Engagement overview for the last 7, 30 or 90 days. Pro plan or higher. (Wraps GET /api/v2/analytics.)

Discovered
get_campaign_review

[read-only] A campaign's pieces grouped into review sections (episode, week, channel set, variant group or the creator's own). Each piece has preview URLs (video / images / audio), caption, labels, its bookings (channels, time, review state) and QA checks; each section has its status, round and every previous fix note. Share `reviewUrl` so a person can preview and decide in flayr. (Wraps GET /api/v2/campaigns/{id}/review.)

Discovered
get_content

[read-only] One content item plus its live posting status: `postState` and `posts[]` (up to 20, newest first) with each post's status (scheduled · publishing · published · partial · failed · review_held · held), scheduledAt, and per-platform status, live URL and error. The item's own `status` stays "draft" after publishing — read `posts` to know whether it is live. Use this to confirm a publish landed. (Wraps GET /api/v2/content/{id}.)

Discovered
get_experiment

[read-only] One experiment: hypothesis, variants, compareKey, window and status. (Wraps GET /api/v2/experiments/{id}.)

Discovered
get_experiment_readout

[read-only] n per arm, pooled reach engagement rate (or average percentage watched when selected), a 90% interval and a hedged verdict (likely_winner, no_clear_winner or not_enough_data). Missing numbers are "not reported" (null), never 0. Say "likely", never "proven". (Wraps GET /api/v2/experiments/{id}/readout.)

Discovered
get_experiment_results

[read-only] The experiment's posts split by its compareKey, with the leading variant by its primary metric and n per arm. Small samples: read medians with their n. (Wraps GET /api/v2/experiments/{id}/results.)

Discovered
get_experiment_rounds

[read-only] A version test's rounds: each closed round's frozen snapshot, the open round's live numbers (null = not reported), the winner if one was recorded, and any repeat-winner proposal. (Wraps GET /api/v2/experiments/{id}/rounds.)

Discovered
get_frame

[read-only] One library frame with its sizes and content areas. (Wraps GET /api/v2/frames/{id}.)

Discovered
get_frame_settings

[read-only] Which frame each platform's images get automatically when a post is published or scheduled. (Wraps GET /api/v2/frames/settings.)

Discovered
get_growth_trigger

[read-only] One trigger with its keywords, texts, link, cap and counts. (Wraps GET /api/v2/growth-triggers/{id}.)

Discovered
get_growth_trigger_stats

[read-only] Matched comments, unique commenters, replies, DMs and failures, in total and per day. (Wraps GET /api/v2/growth-triggers/{id}/stats.)

Discovered
get_job_status

[read-only] Status of an async job (combine_clips, render_motion_ad, or an API video generation): pending, processing, completed or failed. For a combine or a motion ad, `resultContentId` is the new draft once completed; a failed combine is refunded automatically. Poll every 10-30 s — renders take about a minute. (Wraps GET /api/v2/generate/status/{jobId}.)

Discovered
get_post

[read-only] A post (`id` = convexPostId from publish, or posts[].id from get_content): status, slot, platforms, its internal labels and per-platform/account instanceLabels, and while it is scheduled the first comment each platform will publish and whether it can be changed now. (Wraps GET /api/v2/posts/{id}.)

Discovered
get_queue

[read-only] A queue and its items in order, with each item's state (queued · publishing · scheduled · posted · failed · skipped), booked or projected slot, and attribution status. (Wraps GET /api/v2/queues/{id}.)

Discovered
get_text_template

[read-only] One format (text template) with its full structure and example. (Wraps GET /api/v2/text-templates/{id}.)

Discovered
group_campaign_review

[writes flayr data · `write` scope] Puts the campaign's not-yet-sectioned pieces into review sections (groupBy: week, channel_set, variant_group, episode or phase; default the brand's setting). Existing sections and decisions are kept. (Wraps POST /api/v2/campaigns/{id}/review.)

Discovered
hooks_generate

[writes flayr data · `write` scope] Writes a batch of draft hooks (on-screen card + spoken line) from the confirmed offers, claims-checked; blocked ones come back in `dropped`, unsaved. Charges Embers once per call (refunded when nothing usable comes back). Needs the Pro plan or higher. (Wraps POST /api/v2/hook-studio/hooks/generate.)

Discovered
hooks_list

[read-only] The brand's hook bank (filter by status: draft, approved, retired), with each hook's claims result. Free. Needs the Pro plan or higher. (Wraps GET /api/v2/hook-studio/hooks.)

Discovered
hooks_update

[writes flayr data · `write` scope] Edits a hook or sets its status. New copy is claims-checked again; a hook whose claims block cannot be approved. Free. Needs the Pro plan or higher. (Wraps PATCH /api/v2/hook-studio/hooks.)

Discovered
labels_bulk_edit

[writes flayr data · `write` scope] Adds and/or removes labels on up to 100 content items in one call: each item becomes (labels − remove) + add. Published items are fine (labels are metadata). Each item succeeds or fails on its own; read `results`. Removing `source:ai-generated` does not turn a post's AI label off: with no explicit toggle it follows how the media was made, and the result carries a `warning`. For real footage also call update_content with `aiGenerated: false` on each item. (Wraps POST /api/v2/content/labels.)

Discovered
list_approval_groups

[read-only] The same held content as list_approvals, grouped by piece: the variants of one draft (or sharing a `group:<id>` label), with the axes they vary on (theme, hook, audio …), a tally (approved / redo / dropped / open) and each variant's state and slot time. `status` open (default) / redo / approved / dropped / all. Needs the explicit `approve` scope. Agency plan. (Wraps GET /api/v2/approval-groups.)

Discovered
list_approvals

[read-only] Content held for approval that waits on the account owner's decision, newest first: posts filed with publish `requiresApproval: true`, drafts submitted for review, and workflow runs parked at an approval gate. `kind` is "manual" or "workflow". With status "rejected" it lists rejected content instead, with the reviewer's reason (`note`, `reasonChips`), who rejected it and when. Needs the explicit `approve` scope (admin does not include it). Agency plan. (Wraps GET /api/v2/approvals.)

Discovered
list_attribution_rules

[read-only] The brand's "posts like this must carry a credit" rules and its mode (flag / push_down). In push_down mode publish refuses or holds a post missing a required credit — add `credits` with update_content first. (Wraps GET /api/v2/attribution-rules.)

Discovered
list_brands

[read-only] Lists the brands this connection can file content into and publish through. Use an `id` as `brandId` on create_content, publish, queues and analytics tools; "personal" means the account owner's personal accounts. A connection bound to one brand sees only that brand (and personal is null). Each brand has its `website` and a `setup` checklist (hasBrandKey, hasWebsite, hasCtaGoal, adsConnected): set a missing website with brand_profile_update; a brand API key is created by the owner in Settings, never by an agent. (Wraps GET /api/v2/brands.)

Discovered
list_connected_accounts

[read-only] The social accounts a brand can post to — the same set publish would use for that `brandId`: platform, handle, display name, health (healthy, needs_reauth, disconnected) and whether flayr can post there right now (`postable`; Reddit is paused because Reddit closed its API to third-party apps). Call this before publish to pick platforms, and tell the user to reconnect any account that is not healthy at flayr.social/connect. (Wraps GET /api/v2/accounts.)

Discovered
list_content

[read-only] Lists content items (drafts), newest first. Each carries `postState` ("posted" / "scheduled" / null) and `posts[]` (up to 5): where it went out, per platform, with status, live URL and failure reason. (Wraps GET /api/v2/content.)

Discovered
list_experiments

[read-only] A/B experiments. Content joins one by carrying the label `experiment:<id>` plus `<compareKey>:<variant>`. (Wraps GET /api/v2/experiments.)

Discovered
list_frames

[read-only] The brand's frames (borders, overlays, lower thirds, corner tags, quote-card frames, ribbons) plus the built-in flayr frames in the brand colors. Each has a `ref` to pass to apply_frame. (Wraps GET /api/v2/frames.)

Discovered
list_growth_triggers

[read-only] The brand's keyword triggers: a comment matching a keyword gets a public reply and/or a DM. Shows whether each is active and its counts. (Wraps GET /api/v2/growth-triggers.)

Discovered
list_pinterest_boards

[read-only] Boards of the Pinterest account(s) a brand publishes to. Use a board id as `pinterest.boardId` on publish. A board is required; the one you pick is remembered as the brand's default for next time, and a publish that uses the default says so (defaultBoardApplied). (Wraps GET /api/v2/pinterest/boards.)

Discovered
list_post_comments

[read-only] A post's comments-after-publish and reshares, with status (waiting, needs_approval, sent, failed) and the resolved text. (Wraps GET /api/v2/posts/{id}/comments.)

Discovered
list_publish_actions

[read-only] Pending, sent and failed comments-after-publish and reshares of the brand (filter by `status`, e.g. needs_approval or failed), with what each waits on. (Wraps GET /api/v2/automations/actions.)

Discovered
list_queues

[read-only] Posting (drip) queues of one brand. A queue posts one item every cadenceHours at timeOfDay in its timezone, keeping `lookahead` items booked at the platform. (Wraps GET /api/v2/queues.)

Discovered
list_reviews

[read-only] Scheduled posts waiting for (or given) a human sign-off, oldest slot first. `canApprove` tells whether THIS connection may approve each one. (Wraps GET /api/v2/reviews.)

Discovered

Recent measurements

Probe history

View status
Latest stored probes. Raw probe rows are kept for 14 days.
CheckedResultResponseTools
Connected1148 ms135