{
  "schemaVersion": "1.0",
  "item": {
    "slug": "postfast",
    "name": "PostFast",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/peturgeorgievv/postfast",
    "canonicalUrl": "https://clawhub.ai/peturgeorgievv/postfast",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/postfast",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=postfast",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "examples/EXAMPLES.md",
      "examples/batch-scheduling.json",
      "examples/cross-platform-post.json",
      "examples/facebook-reel.json",
      "examples/facebook-story.json"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/postfast"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/postfast",
    "agentPageUrl": "https://openagent3.xyz/skills/postfast/agent",
    "manifestUrl": "https://openagent3.xyz/skills/postfast/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/postfast/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "PostFast",
        "body": "Schedule social media posts across 10 platforms from one API. SaaS — no self-hosting needed."
      },
      {
        "title": "Setup",
        "body": "Sign up at https://app.postfa.st/register (7-day free trial, no credit card)\nGo to Workspace Settings → generate an API key\nSet the environment variable:\nexport POSTFAST_API_KEY=\"your-api-key\"\n\nBase URL: https://api.postfa.st\nAuth header: pf-api-key: $POSTFAST_API_KEY"
      },
      {
        "title": "1. List connected accounts",
        "body": "curl -s -H \"pf-api-key: $POSTFAST_API_KEY\" https://api.postfa.st/social-media/my-social-accounts\n\nReturns array of { id, platform, platformUsername, displayName }. Save the id — it's the socialMediaId required for every post.\n\nPlatform values: TIKTOK, INSTAGRAM, FACEBOOK, X, YOUTUBE, LINKEDIN, THREADS, BLUESKY, PINTEREST, TELEGRAM"
      },
      {
        "title": "2. Schedule a text post (no media)",
        "body": "curl -X POST https://api.postfa.st/social-posts \\\n  -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"posts\": [{\n      \"content\": \"Your post text here\",\n      \"mediaItems\": [],\n      \"scheduledAt\": \"2026-06-15T10:00:00.000Z\",\n      \"socialMediaId\": \"ACCOUNT_ID_HERE\"\n    }],\n    \"controls\": {}\n  }'\n\nReturns { \"postIds\": [\"uuid-1\"] }."
      },
      {
        "title": "3. Schedule a post with media (3-step flow)",
        "body": "Step A — Get signed upload URLs:\n\ncurl -X POST https://api.postfa.st/file/get-signed-upload-urls \\\n  -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"contentType\": \"image/png\", \"count\": 1 }'\n\nReturns [{ \"key\": \"image/uuid.png\", \"signedUrl\": \"https://...\" }].\n\nStep B — Upload file to S3:\n\ncurl -X PUT \"SIGNED_URL_HERE\" \\\n  -H \"Content-Type: image/png\" \\\n  --data-binary @/path/to/file.png\n\nStep C — Create post with media key:\n\ncurl -X POST https://api.postfa.st/social-posts \\\n  -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"posts\": [{\n      \"content\": \"Post with image!\",\n      \"mediaItems\": [{ \"key\": \"image/uuid.png\", \"type\": \"IMAGE\", \"sortOrder\": 0 }],\n      \"scheduledAt\": \"2026-06-15T10:00:00.000Z\",\n      \"socialMediaId\": \"ACCOUNT_ID_HERE\"\n    }],\n    \"controls\": {}\n  }'\n\nFor video: use contentType: \"video/mp4\", type: \"VIDEO\", key prefix video/."
      },
      {
        "title": "4. List scheduled posts",
        "body": "curl -s -H \"pf-api-key: $POSTFAST_API_KEY\" \"https://api.postfa.st/social-posts?page=0&limit=20\"\n\nReturns { \"data\": [...], \"totalCount\": 25, \"pageInfo\": { \"page\": 1, \"hasNextPage\": true, \"perPage\": 20 } }.\n\nQuery parameters:\n\npage (int, default 0) — 0-based page index. Response shows 1-based display page in pageInfo.page\nlimit (int, default 20, max 50) — items per page\nplatforms (string) — comma-separated filter: FACEBOOK,INSTAGRAM,X\nstatuses (string) — comma-separated: DRAFT, SCHEDULED, PUBLISHED, FAILED\nfrom / to (ISO 8601 UTC) — date range filter on scheduledAt\n\nExample: GET /social-posts?page=0&limit=50&platforms=X,LINKEDIN&statuses=SCHEDULED&from=2026-06-01T00:00:00Z&to=2026-06-30T23:59:59Z"
      },
      {
        "title": "5. Delete a scheduled post",
        "body": "curl -X DELETE -H \"pf-api-key: $POSTFAST_API_KEY\" https://api.postfa.st/social-posts/POST_ID"
      },
      {
        "title": "6. Cross-post to multiple platforms",
        "body": "Include multiple entries in the posts array, each with a different socialMediaId. They share the same controls and mediaItems keys."
      },
      {
        "title": "7. Generate a connect link (for clients)",
        "body": "Let clients connect their social accounts to your workspace without creating a PostFast account:\n\ncurl -X POST https://api.postfa.st/social-media/connect-link \\\n  -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"expiryDays\": 7, \"sendEmail\": true, \"email\": \"client@example.com\" }'\n\nReturns { \"connectUrl\": \"https://app.postfa.st/connect?token=...\" }. Share the URL — they can connect accounts directly. Rate limit: 50/hour."
      },
      {
        "title": "8. Create a draft post",
        "body": "Omit scheduledAt and set status: \"DRAFT\" to save without scheduling:\n\ncurl -X POST https://api.postfa.st/social-posts \\\n  -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"posts\": [{ \"content\": \"Draft idea...\", \"mediaItems\": [], \"socialMediaId\": \"ACCOUNT_ID\" }],\n    \"status\": \"DRAFT\",\n    \"controls\": {}\n  }'"
      },
      {
        "title": "9. Get post analytics",
        "body": "Fetch published posts with their performance metrics:\n\ncurl -s -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  \"https://api.postfa.st/social-posts/analytics?startDate=2026-03-01T00:00:00.000Z&endDate=2026-03-31T23:59:59.999Z&platforms=TIKTOK,INSTAGRAM\"\n\nQuery parameters:\n\nstartDate (ISO 8601, required) — start of date range\nendDate (ISO 8601, required) — end of date range\nplatforms (string, optional) — comma-separated filter\nsocialMediaIds (string, optional) — comma-separated account UUIDs\n\nReturns { \"data\": [{ id, content, socialMediaId, platformPostId, publishedAt, latestMetric }] }.\n\nlatestMetric fields: impressions, reach, likes, comments, shares, totalInteractions, fetchedAt, extras. All numbers are strings (bigint). latestMetric is null if metrics haven't been fetched yet. LinkedIn personal accounts are excluded.\n\nRate limit: 350/hour."
      },
      {
        "title": "Pattern 1: Cross-platform campaign",
        "body": "Post the same content to LinkedIn, X, and Threads at the same time:\n\ncurl -X POST https://api.postfa.st/social-posts \\\n  -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"posts\": [\n      { \"content\": \"Big announcement!\", \"mediaItems\": [], \"scheduledAt\": \"2026-06-15T09:00:00.000Z\", \"socialMediaId\": \"LINKEDIN_ID\" },\n      { \"content\": \"Big announcement!\", \"mediaItems\": [], \"scheduledAt\": \"2026-06-15T09:00:00.000Z\", \"socialMediaId\": \"X_ID\" },\n      { \"content\": \"Big announcement!\", \"mediaItems\": [], \"scheduledAt\": \"2026-06-15T09:00:00.000Z\", \"socialMediaId\": \"THREADS_ID\" }\n    ],\n    \"controls\": {}\n  }'\n\nSee examples/cross-platform-post.json for a complete example."
      },
      {
        "title": "Pattern 2: Instagram Reel with upload",
        "body": "Get signed URL with contentType: \"video/mp4\"\nPUT video to signed URL\nCreate post with instagramPublishType: \"REEL\"\n\nSee examples/instagram-reel.json for the request body."
      },
      {
        "title": "Pattern 3: TikTok video with privacy settings",
        "body": "Upload video, then post with privacy controls:\n\n# controls object:\n{\n  \"tiktokPrivacy\": \"PUBLIC\",\n  \"tiktokAllowComments\": true,\n  \"tiktokAllowDuet\": false,\n  \"tiktokAllowStitch\": false,\n  \"tiktokBrandContent\": true\n}\n\nSee examples/tiktok-video.json."
      },
      {
        "title": "Pattern 4: Pinterest pin (board required)",
        "body": "Always fetch boards first, then post:\n\n# Step 1: Get boards\ncurl -s -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  https://api.postfa.st/social-media/PINTEREST_ACCOUNT_ID/pinterest-boards\n\n# Step 2: Post with board ID\n# controls: { \"pinterestBoardId\": \"BOARD_ID\", \"pinterestLink\": \"https://yoursite.com\" }\n\nSee examples/pinterest-pin.json."
      },
      {
        "title": "Pattern 5: YouTube Short with tags and playlist",
        "body": "Upload video, then post with YouTube controls:\n\n# controls object:\n{\n  \"youtubeIsShort\": true,\n  \"youtubeTitle\": \"Quick Tip: Batch Your Content\",\n  \"youtubePrivacy\": \"PUBLIC\",\n  \"youtubePlaylistId\": \"PLxxxxxx\",\n  \"youtubeTags\": [\"tips\", \"productivity\", \"social media\"],\n  \"youtubeMadeForKids\": false\n}\n\nSee examples/youtube-short.json."
      },
      {
        "title": "Pattern 6: LinkedIn document post",
        "body": "Documents (PDF, PPTX, DOCX) display as swipeable carousels on LinkedIn.\n\nGet signed URL with contentType: \"application/pdf\"\nPUT the file to signed URL\nCreate post using linkedinAttachmentKey instead of mediaItems\n\n# controls: { \"linkedinAttachmentKey\": \"file/uuid.pdf\", \"linkedinAttachmentTitle\": \"Q1 Marketing Playbook\" }\n# Note: mediaItems should be [] when using linkedinAttachmentKey\n\nSee examples/linkedin-document.json."
      },
      {
        "title": "Pattern 7: First comment (auto-posted after publish)",
        "body": "Add a firstComment to any post — it's auto-posted ~10 seconds after the main post goes live (up to 3 retries):\n\n{\n  \"posts\": [{ \"content\": \"Main post text\", \"firstComment\": \"Link: https://postfa.st\", \"mediaItems\": [], \"scheduledAt\": \"...\", \"socialMediaId\": \"X_ID\" }],\n  \"controls\": {}\n}\n\nSupported on: X, Instagram, Facebook, YouTube, Threads. NOT supported on: TikTok, Pinterest, Bluesky, LinkedIn.\n\nSee examples/x-first-comment.json."
      },
      {
        "title": "Pattern 8: X (Twitter) retweet",
        "body": "Schedule a retweet — content and media are ignored:\n\n{\n  \"posts\": [{ \"content\": \"\", \"scheduledAt\": \"...\", \"socialMediaId\": \"X_ID\" }],\n  \"controls\": { \"xRetweetUrl\": \"https://x.com/username/status/1234567890\" }\n}\n\nSee examples/x-retweet.json. For quote tweets with your own commentary, use xQuoteTweetUrl instead. See examples/x-quote-tweet.json."
      },
      {
        "title": "Pattern 9: Batch scheduling (a week of posts)",
        "body": "Schedule multiple posts at different times in a single API call (up to 15 posts per request):\n\nSee examples/batch-scheduling.json."
      },
      {
        "title": "Platform-Specific Controls",
        "body": "Pass these in the controls object. See references/platform-controls.md for full details.\n\nPlatformKey ControlsTikToktiktokPrivacy, tiktokAllowComments, tiktokAllowDuet, tiktokAllowStitch, tiktokIsDraft, tiktokBrandOrganic, tiktokBrandContent, tiktokAutoAddMusicInstagraminstagramPublishType (TIMELINE/STORY/REEL), instagramPostToGrid, instagramCollaboratorsFacebookfacebookContentType (POST/REEL/STORY), facebookReelsCollaboratorsYouTubeyoutubeIsShort, youtubeTitle, youtubePrivacy, youtubePlaylistId, youtubeTags, youtubeMadeForKids, youtubeCategoryIdLinkedInlinkedinAttachmentKey, linkedinAttachmentTitle (for document posts)X (Twitter)xQuoteTweetUrl (quote tweet), xRetweetUrl (retweet), xCommunityId (post to community)PinterestpinterestBoardId (required), pinterestLinkBlueskyNo platform-specific controls — text + images onlyThreadsNo platform-specific controls — text + images/videoTelegramNo platform-specific controls — text + images/video/mixed media"
      },
      {
        "title": "Helper Endpoints",
        "body": "Pinterest boards: GET /social-media/{id}/pinterest-boards → returns [{ boardId, name }]\nYouTube playlists: GET /social-media/{id}/youtube-playlists → returns [{ playlistId, title }]\nConnect link: POST /social-media/connect-link → returns { connectUrl }. Let clients connect accounts without a PostFast account. Params: expiryDays (1-30, default 7), sendEmail (bool), email (required if sendEmail=true)"
      },
      {
        "title": "Rate Limits",
        "body": "Global (per API key): 60/min, 150/5min, 300/hour, 2000/day\n\nPer-endpoint:\n\nPOST /social-posts: 350/day\nGET /social-posts: 200/hour\nGET /social-posts/analytics: 350/hour\nPOST /social-media/connect-link: 50/hour\n\nPlatform limits:\n\nX (Twitter) via API: 5 posts per account per day — do not exceed this\n\nCheck X-RateLimit-Remaining-* headers. 429 = rate limited, check Retry-After-* header. For batch operations, add a 1-second delay between API calls."
      },
      {
        "title": "Media Specs Quick Reference",
        "body": "PlatformImagesVideoCarouselTikTokCarousels only≤250MB, MP4/MOV, 3s-10min2-35 imagesInstagramJPEG/PNG≤1GB, 3-90s (Reels)Up to 10Facebook≤30MB, JPG/PNG1 per postUp to 10 imagesYouTube—Shorts ≤3min, H.264—LinkedInUp to 9≤10minUp to 9, or documents (PDF/PPTX/DOCX)X (Twitter)Up to 4——Pinterest2:3 ratio idealSupported2-5 imagesBlueskyUp to 4Not supported—ThreadsSupportedSupportedUp to 10TelegramUp to 10SupportedUp to 10 mixed media"
      },
      {
        "title": "Common Gotchas",
        "body": "Always fetch accounts first — socialMediaId is a UUID, not a platform name. Call GET /social-media/my-social-accounts to get valid IDs.\nMedia MUST go through 3-step upload — No external URLs. Always: get signed URL → PUT to S3 → use the key in mediaItems.\nscheduledAt must be in the future — ISO 8601 UTC format. Past dates return 400.\nPinterest ALWAYS requires pinterestBoardId — Fetch boards first with GET /social-media/{id}/pinterest-boards.\nTikTok requires video for standard posts — Images only work in carousels (2-35 images).\nLinkedIn documents use linkedinAttachmentKey — NOT mediaItems. Set mediaItems: [] when posting documents.\nContent-Type on S3 PUT must match — The Content-Type header in your S3 PUT must match what you requested in get-signed-upload-urls.\nInstagram Reels need video 3-90 seconds — Outside this range returns an error.\nYouTube Shorts need video under 3 minutes — H.264 codec with AAC audio recommended.\nX (Twitter) has a 280 character limit — Longer content is silently truncated.\nCross-posting shares controls — The controls object applies to ALL posts in the batch. Platform-irrelevant controls are ignored.\nX (Twitter) API limit is 5 posts/account/day — Exceeding this risks account restrictions.\nfirstComment only works on 5 platforms — X, Instagram, Facebook, YouTube, Threads. TikTok, Pinterest, Bluesky, LinkedIn return a validation error.\nCannot use xQuoteTweetUrl and xRetweetUrl together — Pick one. Retweets ignore content/media.\nLinkedIn documents support PDF, DOC, DOCX, PPT, PPTX — Max 60MB. Cannot mix with regular media.\nPagination is 0-based — page=0 returns the first page. Response pageInfo.page shows 1-based display number."
      },
      {
        "title": "Supporting Resources",
        "body": "Reference docs:\n\nreferences/api-reference.md — Complete API endpoint reference with response examples\nreferences/platform-controls.md — All platform-specific controls with types and defaults\nreferences/media-specs.md — Media size, format, and dimension limits per platform\nreferences/upload-flow.md — Detailed media upload walkthrough\n\nReady-to-use examples:\n\nexamples/EXAMPLES.md — Index of all 18 examples\nexamples/cross-platform-post.json — Multi-platform posting\nexamples/tiktok-video.json — TikTok with privacy settings\nexamples/tiktok-carousel.json — TikTok image carousel\nexamples/tiktok-draft.json — TikTok saved as draft\nexamples/instagram-reel.json — Instagram Reel\nexamples/instagram-story.json — Instagram Story\nexamples/instagram-carousel.json — Instagram carousel\nexamples/facebook-reel.json — Facebook Reel\nexamples/facebook-story.json — Facebook Story\nexamples/youtube-short.json — YouTube Short with tags\nexamples/pinterest-pin.json — Pinterest with board\nexamples/linkedin-document.json — LinkedIn document post\nexamples/x-quote-tweet.json — X quote tweet\nexamples/x-retweet.json — X scheduled retweet\nexamples/x-first-comment.json — X post with auto first comment\nexamples/threads-carousel.json — Threads image carousel\nexamples/batch-scheduling.json — Week of scheduled posts\nexamples/telegram-mixed-media.json — Telegram mixed media"
      },
      {
        "title": "Quick Reference",
        "body": "# Auth\nHeader: pf-api-key: $POSTFAST_API_KEY\n\n# List accounts\nGET /social-media/my-social-accounts\n\n# Schedule post\nPOST /social-posts  { posts: [{ content, mediaItems, scheduledAt, socialMediaId, firstComment? }], status?, approvalStatus?, controls: {} }\n\n# Draft post (no scheduledAt needed)\nPOST /social-posts  { posts: [...], status: \"DRAFT\", controls: {} }\n\n# List posts (page is 0-based, limit max 50)\nGET /social-posts?page=0&limit=20\nGET /social-posts?page=0&limit=50&platforms=X,LINKEDIN&statuses=SCHEDULED&from=2026-06-01T00:00:00Z&to=2026-06-30T23:59:59Z\n\n# Delete post\nDELETE /social-posts/:id\n\n# Upload media (3 steps)\nPOST /file/get-signed-upload-urls  { contentType, count }\nPUT  <signedUrl>  (raw file, matching Content-Type)\n# then use key in mediaItems\n\n# Pinterest boards\nGET /social-media/:id/pinterest-boards\n\n# YouTube playlists\nGET /social-media/:id/youtube-playlists\n\n# Post analytics (published posts with metrics)\nGET /social-posts/analytics?startDate=...&endDate=...&platforms=...\n\n# Connect link (for clients)\nPOST /social-media/connect-link  { expiryDays?, sendEmail?, email? }"
      },
      {
        "title": "Tips for the Agent",
        "body": "Always call my-social-accounts first to get valid socialMediaId values.\nFor media posts, complete the full 3-step upload flow (signed URL → S3 PUT → create post).\nscheduledAt must be ISO 8601 UTC and in the future.\nPinterest always requires pinterestBoardId — fetch boards first.\nLinkedIn documents use linkedinAttachmentKey instead of mediaItems.\nFor carousels, include multiple items in mediaItems with sequential sortOrder.\nTikTok video thumbnails: set coverTimestamp (seconds) in mediaItems.\nWhen cross-posting, adjust content length for each platform's limits (X: 280, Bluesky: 300, TikTok: 2200).\nIf the user doesn't specify a time, suggest tomorrow at 9:00 AM in their timezone.\nBatch up to 15 posts per API call for efficiency.\nUse firstComment for CTAs and links — keeps the main post clean and gets better engagement.\nX (Twitter) allows only 5 posts per account per day via API — warn the user if they're batching many X posts.\nFor draft posts, set status: \"DRAFT\" and omit scheduledAt — the user can finalize in the PostFast dashboard.\nUse GET /social-posts with from/to filters to check what's already scheduled before adding more."
      }
    ],
    "body": "PostFast\n\nSchedule social media posts across 10 platforms from one API. SaaS — no self-hosting needed.\n\nSetup\nSign up at https://app.postfa.st/register (7-day free trial, no credit card)\nGo to Workspace Settings → generate an API key\nSet the environment variable:\nexport POSTFAST_API_KEY=\"your-api-key\"\n\n\nBase URL: https://api.postfa.st Auth header: pf-api-key: $POSTFAST_API_KEY\n\nCore Workflow\n1. List connected accounts\ncurl -s -H \"pf-api-key: $POSTFAST_API_KEY\" https://api.postfa.st/social-media/my-social-accounts\n\n\nReturns array of { id, platform, platformUsername, displayName }. Save the id — it's the socialMediaId required for every post.\n\nPlatform values: TIKTOK, INSTAGRAM, FACEBOOK, X, YOUTUBE, LINKEDIN, THREADS, BLUESKY, PINTEREST, TELEGRAM\n\n2. Schedule a text post (no media)\ncurl -X POST https://api.postfa.st/social-posts \\\n  -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"posts\": [{\n      \"content\": \"Your post text here\",\n      \"mediaItems\": [],\n      \"scheduledAt\": \"2026-06-15T10:00:00.000Z\",\n      \"socialMediaId\": \"ACCOUNT_ID_HERE\"\n    }],\n    \"controls\": {}\n  }'\n\n\nReturns { \"postIds\": [\"uuid-1\"] }.\n\n3. Schedule a post with media (3-step flow)\n\nStep A — Get signed upload URLs:\n\ncurl -X POST https://api.postfa.st/file/get-signed-upload-urls \\\n  -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"contentType\": \"image/png\", \"count\": 1 }'\n\n\nReturns [{ \"key\": \"image/uuid.png\", \"signedUrl\": \"https://...\" }].\n\nStep B — Upload file to S3:\n\ncurl -X PUT \"SIGNED_URL_HERE\" \\\n  -H \"Content-Type: image/png\" \\\n  --data-binary @/path/to/file.png\n\n\nStep C — Create post with media key:\n\ncurl -X POST https://api.postfa.st/social-posts \\\n  -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"posts\": [{\n      \"content\": \"Post with image!\",\n      \"mediaItems\": [{ \"key\": \"image/uuid.png\", \"type\": \"IMAGE\", \"sortOrder\": 0 }],\n      \"scheduledAt\": \"2026-06-15T10:00:00.000Z\",\n      \"socialMediaId\": \"ACCOUNT_ID_HERE\"\n    }],\n    \"controls\": {}\n  }'\n\n\nFor video: use contentType: \"video/mp4\", type: \"VIDEO\", key prefix video/.\n\n4. List scheduled posts\ncurl -s -H \"pf-api-key: $POSTFAST_API_KEY\" \"https://api.postfa.st/social-posts?page=0&limit=20\"\n\n\nReturns { \"data\": [...], \"totalCount\": 25, \"pageInfo\": { \"page\": 1, \"hasNextPage\": true, \"perPage\": 20 } }.\n\nQuery parameters:\n\npage (int, default 0) — 0-based page index. Response shows 1-based display page in pageInfo.page\nlimit (int, default 20, max 50) — items per page\nplatforms (string) — comma-separated filter: FACEBOOK,INSTAGRAM,X\nstatuses (string) — comma-separated: DRAFT, SCHEDULED, PUBLISHED, FAILED\nfrom / to (ISO 8601 UTC) — date range filter on scheduledAt\n\nExample: GET /social-posts?page=0&limit=50&platforms=X,LINKEDIN&statuses=SCHEDULED&from=2026-06-01T00:00:00Z&to=2026-06-30T23:59:59Z\n\n5. Delete a scheduled post\ncurl -X DELETE -H \"pf-api-key: $POSTFAST_API_KEY\" https://api.postfa.st/social-posts/POST_ID\n\n6. Cross-post to multiple platforms\n\nInclude multiple entries in the posts array, each with a different socialMediaId. They share the same controls and mediaItems keys.\n\n7. Generate a connect link (for clients)\n\nLet clients connect their social accounts to your workspace without creating a PostFast account:\n\ncurl -X POST https://api.postfa.st/social-media/connect-link \\\n  -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"expiryDays\": 7, \"sendEmail\": true, \"email\": \"client@example.com\" }'\n\n\nReturns { \"connectUrl\": \"https://app.postfa.st/connect?token=...\" }. Share the URL — they can connect accounts directly. Rate limit: 50/hour.\n\n8. Create a draft post\n\nOmit scheduledAt and set status: \"DRAFT\" to save without scheduling:\n\ncurl -X POST https://api.postfa.st/social-posts \\\n  -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"posts\": [{ \"content\": \"Draft idea...\", \"mediaItems\": [], \"socialMediaId\": \"ACCOUNT_ID\" }],\n    \"status\": \"DRAFT\",\n    \"controls\": {}\n  }'\n\n9. Get post analytics\n\nFetch published posts with their performance metrics:\n\ncurl -s -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  \"https://api.postfa.st/social-posts/analytics?startDate=2026-03-01T00:00:00.000Z&endDate=2026-03-31T23:59:59.999Z&platforms=TIKTOK,INSTAGRAM\"\n\n\nQuery parameters:\n\nstartDate (ISO 8601, required) — start of date range\nendDate (ISO 8601, required) — end of date range\nplatforms (string, optional) — comma-separated filter\nsocialMediaIds (string, optional) — comma-separated account UUIDs\n\nReturns { \"data\": [{ id, content, socialMediaId, platformPostId, publishedAt, latestMetric }] }.\n\nlatestMetric fields: impressions, reach, likes, comments, shares, totalInteractions, fetchedAt, extras. All numbers are strings (bigint). latestMetric is null if metrics haven't been fetched yet. LinkedIn personal accounts are excluded.\n\nRate limit: 350/hour.\n\nCommon Patterns\nPattern 1: Cross-platform campaign\n\nPost the same content to LinkedIn, X, and Threads at the same time:\n\ncurl -X POST https://api.postfa.st/social-posts \\\n  -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"posts\": [\n      { \"content\": \"Big announcement!\", \"mediaItems\": [], \"scheduledAt\": \"2026-06-15T09:00:00.000Z\", \"socialMediaId\": \"LINKEDIN_ID\" },\n      { \"content\": \"Big announcement!\", \"mediaItems\": [], \"scheduledAt\": \"2026-06-15T09:00:00.000Z\", \"socialMediaId\": \"X_ID\" },\n      { \"content\": \"Big announcement!\", \"mediaItems\": [], \"scheduledAt\": \"2026-06-15T09:00:00.000Z\", \"socialMediaId\": \"THREADS_ID\" }\n    ],\n    \"controls\": {}\n  }'\n\n\nSee examples/cross-platform-post.json for a complete example.\n\nPattern 2: Instagram Reel with upload\nGet signed URL with contentType: \"video/mp4\"\nPUT video to signed URL\nCreate post with instagramPublishType: \"REEL\"\n\nSee examples/instagram-reel.json for the request body.\n\nPattern 3: TikTok video with privacy settings\n\nUpload video, then post with privacy controls:\n\n# controls object:\n{\n  \"tiktokPrivacy\": \"PUBLIC\",\n  \"tiktokAllowComments\": true,\n  \"tiktokAllowDuet\": false,\n  \"tiktokAllowStitch\": false,\n  \"tiktokBrandContent\": true\n}\n\n\nSee examples/tiktok-video.json.\n\nPattern 4: Pinterest pin (board required)\n\nAlways fetch boards first, then post:\n\n# Step 1: Get boards\ncurl -s -H \"pf-api-key: $POSTFAST_API_KEY\" \\\n  https://api.postfa.st/social-media/PINTEREST_ACCOUNT_ID/pinterest-boards\n\n# Step 2: Post with board ID\n# controls: { \"pinterestBoardId\": \"BOARD_ID\", \"pinterestLink\": \"https://yoursite.com\" }\n\n\nSee examples/pinterest-pin.json.\n\nPattern 5: YouTube Short with tags and playlist\n\nUpload video, then post with YouTube controls:\n\n# controls object:\n{\n  \"youtubeIsShort\": true,\n  \"youtubeTitle\": \"Quick Tip: Batch Your Content\",\n  \"youtubePrivacy\": \"PUBLIC\",\n  \"youtubePlaylistId\": \"PLxxxxxx\",\n  \"youtubeTags\": [\"tips\", \"productivity\", \"social media\"],\n  \"youtubeMadeForKids\": false\n}\n\n\nSee examples/youtube-short.json.\n\nPattern 6: LinkedIn document post\n\nDocuments (PDF, PPTX, DOCX) display as swipeable carousels on LinkedIn.\n\nGet signed URL with contentType: \"application/pdf\"\nPUT the file to signed URL\nCreate post using linkedinAttachmentKey instead of mediaItems\n# controls: { \"linkedinAttachmentKey\": \"file/uuid.pdf\", \"linkedinAttachmentTitle\": \"Q1 Marketing Playbook\" }\n# Note: mediaItems should be [] when using linkedinAttachmentKey\n\n\nSee examples/linkedin-document.json.\n\nPattern 7: First comment (auto-posted after publish)\n\nAdd a firstComment to any post — it's auto-posted ~10 seconds after the main post goes live (up to 3 retries):\n\n{\n  \"posts\": [{ \"content\": \"Main post text\", \"firstComment\": \"Link: https://postfa.st\", \"mediaItems\": [], \"scheduledAt\": \"...\", \"socialMediaId\": \"X_ID\" }],\n  \"controls\": {}\n}\n\n\nSupported on: X, Instagram, Facebook, YouTube, Threads. NOT supported on: TikTok, Pinterest, Bluesky, LinkedIn.\n\nSee examples/x-first-comment.json.\n\nPattern 8: X (Twitter) retweet\n\nSchedule a retweet — content and media are ignored:\n\n{\n  \"posts\": [{ \"content\": \"\", \"scheduledAt\": \"...\", \"socialMediaId\": \"X_ID\" }],\n  \"controls\": { \"xRetweetUrl\": \"https://x.com/username/status/1234567890\" }\n}\n\n\nSee examples/x-retweet.json. For quote tweets with your own commentary, use xQuoteTweetUrl instead. See examples/x-quote-tweet.json.\n\nPattern 9: Batch scheduling (a week of posts)\n\nSchedule multiple posts at different times in a single API call (up to 15 posts per request):\n\nSee examples/batch-scheduling.json.\n\nPlatform-Specific Controls\n\nPass these in the controls object. See references/platform-controls.md for full details.\n\nPlatform\tKey Controls\nTikTok\ttiktokPrivacy, tiktokAllowComments, tiktokAllowDuet, tiktokAllowStitch, tiktokIsDraft, tiktokBrandOrganic, tiktokBrandContent, tiktokAutoAddMusic\nInstagram\tinstagramPublishType (TIMELINE/STORY/REEL), instagramPostToGrid, instagramCollaborators\nFacebook\tfacebookContentType (POST/REEL/STORY), facebookReelsCollaborators\nYouTube\tyoutubeIsShort, youtubeTitle, youtubePrivacy, youtubePlaylistId, youtubeTags, youtubeMadeForKids, youtubeCategoryId\nLinkedIn\tlinkedinAttachmentKey, linkedinAttachmentTitle (for document posts)\nX (Twitter)\txQuoteTweetUrl (quote tweet), xRetweetUrl (retweet), xCommunityId (post to community)\nPinterest\tpinterestBoardId (required), pinterestLink\nBluesky\tNo platform-specific controls — text + images only\nThreads\tNo platform-specific controls — text + images/video\nTelegram\tNo platform-specific controls — text + images/video/mixed media\nHelper Endpoints\nPinterest boards: GET /social-media/{id}/pinterest-boards → returns [{ boardId, name }]\nYouTube playlists: GET /social-media/{id}/youtube-playlists → returns [{ playlistId, title }]\nConnect link: POST /social-media/connect-link → returns { connectUrl }. Let clients connect accounts without a PostFast account. Params: expiryDays (1-30, default 7), sendEmail (bool), email (required if sendEmail=true)\nRate Limits\n\nGlobal (per API key): 60/min, 150/5min, 300/hour, 2000/day\n\nPer-endpoint:\n\nPOST /social-posts: 350/day\nGET /social-posts: 200/hour\nGET /social-posts/analytics: 350/hour\nPOST /social-media/connect-link: 50/hour\n\nPlatform limits:\n\nX (Twitter) via API: 5 posts per account per day — do not exceed this\n\nCheck X-RateLimit-Remaining-* headers. 429 = rate limited, check Retry-After-* header. For batch operations, add a 1-second delay between API calls.\n\nMedia Specs Quick Reference\nPlatform\tImages\tVideo\tCarousel\nTikTok\tCarousels only\t≤250MB, MP4/MOV, 3s-10min\t2-35 images\nInstagram\tJPEG/PNG\t≤1GB, 3-90s (Reels)\tUp to 10\nFacebook\t≤30MB, JPG/PNG\t1 per post\tUp to 10 images\nYouTube\t—\tShorts ≤3min, H.264\t—\nLinkedIn\tUp to 9\t≤10min\tUp to 9, or documents (PDF/PPTX/DOCX)\nX (Twitter)\tUp to 4\t—\t—\nPinterest\t2:3 ratio ideal\tSupported\t2-5 images\nBluesky\tUp to 4\tNot supported\t—\nThreads\tSupported\tSupported\tUp to 10\nTelegram\tUp to 10\tSupported\tUp to 10 mixed media\nCommon Gotchas\nAlways fetch accounts first — socialMediaId is a UUID, not a platform name. Call GET /social-media/my-social-accounts to get valid IDs.\nMedia MUST go through 3-step upload — No external URLs. Always: get signed URL → PUT to S3 → use the key in mediaItems.\nscheduledAt must be in the future — ISO 8601 UTC format. Past dates return 400.\nPinterest ALWAYS requires pinterestBoardId — Fetch boards first with GET /social-media/{id}/pinterest-boards.\nTikTok requires video for standard posts — Images only work in carousels (2-35 images).\nLinkedIn documents use linkedinAttachmentKey — NOT mediaItems. Set mediaItems: [] when posting documents.\nContent-Type on S3 PUT must match — The Content-Type header in your S3 PUT must match what you requested in get-signed-upload-urls.\nInstagram Reels need video 3-90 seconds — Outside this range returns an error.\nYouTube Shorts need video under 3 minutes — H.264 codec with AAC audio recommended.\nX (Twitter) has a 280 character limit — Longer content is silently truncated.\nCross-posting shares controls — The controls object applies to ALL posts in the batch. Platform-irrelevant controls are ignored.\nX (Twitter) API limit is 5 posts/account/day — Exceeding this risks account restrictions.\nfirstComment only works on 5 platforms — X, Instagram, Facebook, YouTube, Threads. TikTok, Pinterest, Bluesky, LinkedIn return a validation error.\nCannot use xQuoteTweetUrl and xRetweetUrl together — Pick one. Retweets ignore content/media.\nLinkedIn documents support PDF, DOC, DOCX, PPT, PPTX — Max 60MB. Cannot mix with regular media.\nPagination is 0-based — page=0 returns the first page. Response pageInfo.page shows 1-based display number.\nSupporting Resources\n\nReference docs:\n\nreferences/api-reference.md — Complete API endpoint reference with response examples\nreferences/platform-controls.md — All platform-specific controls with types and defaults\nreferences/media-specs.md — Media size, format, and dimension limits per platform\nreferences/upload-flow.md — Detailed media upload walkthrough\n\nReady-to-use examples:\n\nexamples/EXAMPLES.md — Index of all 18 examples\nexamples/cross-platform-post.json — Multi-platform posting\nexamples/tiktok-video.json — TikTok with privacy settings\nexamples/tiktok-carousel.json — TikTok image carousel\nexamples/tiktok-draft.json — TikTok saved as draft\nexamples/instagram-reel.json — Instagram Reel\nexamples/instagram-story.json — Instagram Story\nexamples/instagram-carousel.json — Instagram carousel\nexamples/facebook-reel.json — Facebook Reel\nexamples/facebook-story.json — Facebook Story\nexamples/youtube-short.json — YouTube Short with tags\nexamples/pinterest-pin.json — Pinterest with board\nexamples/linkedin-document.json — LinkedIn document post\nexamples/x-quote-tweet.json — X quote tweet\nexamples/x-retweet.json — X scheduled retweet\nexamples/x-first-comment.json — X post with auto first comment\nexamples/threads-carousel.json — Threads image carousel\nexamples/batch-scheduling.json — Week of scheduled posts\nexamples/telegram-mixed-media.json — Telegram mixed media\nQuick Reference\n# Auth\nHeader: pf-api-key: $POSTFAST_API_KEY\n\n# List accounts\nGET /social-media/my-social-accounts\n\n# Schedule post\nPOST /social-posts  { posts: [{ content, mediaItems, scheduledAt, socialMediaId, firstComment? }], status?, approvalStatus?, controls: {} }\n\n# Draft post (no scheduledAt needed)\nPOST /social-posts  { posts: [...], status: \"DRAFT\", controls: {} }\n\n# List posts (page is 0-based, limit max 50)\nGET /social-posts?page=0&limit=20\nGET /social-posts?page=0&limit=50&platforms=X,LINKEDIN&statuses=SCHEDULED&from=2026-06-01T00:00:00Z&to=2026-06-30T23:59:59Z\n\n# Delete post\nDELETE /social-posts/:id\n\n# Upload media (3 steps)\nPOST /file/get-signed-upload-urls  { contentType, count }\nPUT  <signedUrl>  (raw file, matching Content-Type)\n# then use key in mediaItems\n\n# Pinterest boards\nGET /social-media/:id/pinterest-boards\n\n# YouTube playlists\nGET /social-media/:id/youtube-playlists\n\n# Post analytics (published posts with metrics)\nGET /social-posts/analytics?startDate=...&endDate=...&platforms=...\n\n# Connect link (for clients)\nPOST /social-media/connect-link  { expiryDays?, sendEmail?, email? }\n\nTips for the Agent\nAlways call my-social-accounts first to get valid socialMediaId values.\nFor media posts, complete the full 3-step upload flow (signed URL → S3 PUT → create post).\nscheduledAt must be ISO 8601 UTC and in the future.\nPinterest always requires pinterestBoardId — fetch boards first.\nLinkedIn documents use linkedinAttachmentKey instead of mediaItems.\nFor carousels, include multiple items in mediaItems with sequential sortOrder.\nTikTok video thumbnails: set coverTimestamp (seconds) in mediaItems.\nWhen cross-posting, adjust content length for each platform's limits (X: 280, Bluesky: 300, TikTok: 2200).\nIf the user doesn't specify a time, suggest tomorrow at 9:00 AM in their timezone.\nBatch up to 15 posts per API call for efficiency.\nUse firstComment for CTAs and links — keeps the main post clean and gets better engagement.\nX (Twitter) allows only 5 posts per account per day via API — warn the user if they're batching many X posts.\nFor draft posts, set status: \"DRAFT\" and omit scheduledAt — the user can finalize in the PostFast dashboard.\nUse GET /social-posts with from/to filters to check what's already scheduled before adding more."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/peturgeorgievv/postfast",
    "publisherUrl": "https://clawhub.ai/peturgeorgievv/postfast",
    "owner": "peturgeorgievv",
    "version": "1.3.1",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/postfast",
    "downloadUrl": "https://openagent3.xyz/downloads/postfast",
    "agentUrl": "https://openagent3.xyz/skills/postfast/agent",
    "manifestUrl": "https://openagent3.xyz/skills/postfast/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/postfast/agent.md"
  }
}