Postfalcon API

A small REST API for managing connected accounts and scheduled posts — the same API the built-in MCP server uses, available for your own scripts and agents.

Authentication

Generate a personal API token from Settings → API access for agents (you'll need an account first). Send it as a bearer token on every request:

Authorization: Bearer pf_<your token>

A token is shown once at creation time. Generating a new one immediately invalidates the old one.

Base URL & versioning

All endpoints below live under /api/v1. This prefix is a stability guarantee — existing fields and behavior won't change under v1; a breaking change would ship as /api/v2 instead, so integrations built against v1 keep working.

Rate limits & CORS

Requests are limited to 300 per 15 minutes, per token. Limit status is reported via the standard RateLimit-* response headers.

The /api/v1 API is CORS-enabled for any origin, so it can be called directly from a browser-based tool using a token — not just server-to-server.

Endpoints

Method & pathDescription
GET /api/v1/social-accountsList your connected social accounts. needs_reconnect_at / reconnect_reason are set when the platform rejected the account's credentials (posts to it will fail until it's reconnected); expires_soon is true when a non-refreshable token expires within 7 days
POST /api/v1/social-accountsConnect an account (platform, display_name, ...)
DELETE /api/v1/social-accounts/:idDisconnect an account
GET /api/v1/postsList posts — filter with ?status= and ?social_account_id=
GET /api/v1/posts/:idGet a single post
POST /api/v1/postsCreate a draft or scheduled post (social_account_id or social_account_ids, content, optional scheduled_for or publish_now: true (published on the next scheduler run, within a minute), repeat_interval, repeat_until, tiktok_options, youtube_options)
PATCH /api/v1/posts/:idUpdate a post's content, status, schedule, repeat settings, tiktok_options, or youtube_options; publish_now: true sends a draft out within a minute
DELETE /api/v1/posts/:idDelete a post
GET /api/v1/analytics/summaryPosts, views, likes, comments and shares for posts published in a period (?days=7|30|90, default 7; ?tz= an IANA timezone for day buckets, default UTC): per-day series, per-platform breakdown, top posts, plus all-time totals. A metric is null when no post in scope reports it.
GET /api/v1/webhooksList your webhook endpoints (Team & Pro plans)
POST /api/v1/webhooksRegister an endpoint (url, optional events) — returns the signing secret once
DELETE /api/v1/webhooks/:idRemove a webhook endpoint

Cross-posting

Pass social_account_ids (a JSON array, or a repeated form field) instead of social_account_id to publish the same content to several channels at once. Postfalcon creates one post per channel, all sharing a crosspost_group_id, and the response is { "crosspost_group_id": "…", "posts": […] }. A single-channel request is unchanged — it still returns the bare post object. Cross-posting requires a plan with the capability (all current paid plans).

Repeated posts

Add repeat_interval (daily, weekly, or monthly) to a scheduled post to make it recurring. Optionally set repeat_until (ISO 8601) to stop after a date; otherwise it runs for up to a year. When an occurrence publishes, Postfalcon queues the next one automatically with its own copy of any attached media.

TikTok settings

TikTok requires the person posting to choose each video's audience and interaction settings. Pass tiktok_options (an object, or a JSON string in a multipart request) with privacy_level (PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR, or SELF_ONLY), and the booleans allow_comment, allow_duet, allow_stitch, brand_organic (promoting yourself), and brand_content (a paid partnership, which can't be SELF_ONLY). Every boolean defaults to false. It only applies to the TikTok channels of a cross-post. A TikTok post without a privacy_level publishes as SELF_ONLY with interactions off; a level TikTok no longer offers for the account fails the post rather than being swapped for another.

YouTube settings

Pass youtube_options (an object, or a JSON string in a multipart request) with title (up to 100 characters, no < or >), privacy_status (public, unlisted, or private), and made_for_kids (boolean, default false). The post's content becomes the video description. Without a title the first 100 characters of the content are used, and without a privacy_status the video uploads as private. Like tiktok_options, it only applies to the YouTube channels of a cross-post.

Analytics

A few times a day, Postfalcon pulls fresh view/like/comment/share counts for your recently-posted content straight from each platform's API and stores the latest snapshot on the post. Coverage varies by platform: Bluesky, Facebook, Instagram, Mastodon, Threads, and YouTube report likes and comments (YouTube and Threads also report views); Telegram and TikTok don't expose post metrics through their APIs, so those posts stay unmetered. GET /api/v1/posts includes the raw metric_views / metric_likes / metric_comments / metric_shares / metrics_updated_at fields on every post (null until a platform reports something); GET /api/v1/analytics/summary aggregates them into a ready-to-chart response:

{
  "days": [{ "date": "2026-09-09", "views": 412, "likes": 38, "comments": 5 }, ...],
  "totals": { "views": 3120, "likes": 266, "comments": 41, "shares": 9 },
  "postsWithMetrics": 14,
  "postsPosted": 16,
  "topPost": { "id": 812, "platform": "youtube", "content": "...", "metric_views": 1204, ... }
}

Webhooks

Register an HTTPS endpoint and Postfalcon will POST it a JSON body whenever one of your posts is published or fails:

{
  "event": "post.published",
  "sent_at": "2026-09-10T12:00:00.000Z",
  "data": {
    "post_id": 42,
    "platform": "mastodon",
    "platform_post_id": "109...",
    "scheduled_for": "2026-09-10T12:00:00.000Z"
  }
}

Events are post.published and post.failed (a failure payload carries error instead of the platform id). Every request is signed so you can verify it came from Postfalcon:

X-Postfalcon-Event: post.published
X-Postfalcon-Signature: sha256=<hex>

The signature is HMAC-SHA256(secret, rawRequestBody), hex-encoded. The secret is shown once when you create the webhook. Deliveries time out after 8 seconds and are not retried; the last delivery's timestamp and HTTP status are visible in Settings. Webhooks are available on the Team and Pro plans.

Example

curl https://your-postfalcon-host/api/v1/posts \
  -H "Authorization: Bearer pf_<your token>" \
  -H "Content-Type: application/json" \
  -d '{"social_account_id": 1, "content": "Hello from the API", "scheduled_for": "2026-08-01T12:00:00Z"}'

Errors

Errors are JSON with an error key, e.g. { "error": "not found" }. Validation failures use:

{ "error": "validation_failed", "details": { "fieldErrors": { "content": ["Required"] } } }

Any AI agent

Postfalcon ships an MCP server built on this same API, in two forms depending on how your agent connects — both expose the same 6 tools (list_accounts, list_posts, create_post, update_post, delete_post, get_analytics_summary):

  • A local command (Claude Desktop, Cursor's command-style config, or any client that spawns a process): from a clone of the Postfalcon repo, run node mcp/server.js with POSTFALCON_BASE_URL and POSTFALCON_API_TOKEN set to your host and token.
  • A URL (ChatGPT, Claude.ai, Cursor's url-style config, OpenClaw, or any other client that speaks Streamable HTTP): point it at https://your-postfalcon-host/mcp with your token as a standard bearer header — no local process to run.
Authorization: Bearer pf_<your token>

Not an MCP client? The plain REST API above works from anywhere that can make an HTTPS request with a bearer token — a Custom GPT Action, a script, or any other agent.