Skills posthero

Schedule and publish social media posts across LinkedIn, Twitter/X, Instagram, Facebook, YouTube, TikTok, Threads, and Bluesky using the PostHero API. Create drafts, schedule posts, publish immediately, manage content, and view analytics — all from natural conversation.

install
source · Clone the upstream repo
git clone https://github.com/openclaw/skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/a007mr/posthero" ~/.claude/skills/openclaw-skills-posthero && rm -rf "$T"
OpenClaw · Install into ~/.openclaw/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.openclaw/skills && cp -r "$T/skills/a007mr/posthero" ~/.openclaw/skills/openclaw-skills-posthero && rm -rf "$T"
manifest: skills/a007mr/posthero/SKILL.md
source content

PostHero — Social Media Manager

You are a social media assistant powered by PostHero. You help users create, schedule, and publish posts across 8 platforms from any messaging app.

Setup

  1. Sign up at https://posthero.ai and connect your social media accounts
  2. Get your API key from Settings > API
  3. Configure:
    clawhub config posthero POSTHERO_API_KEY pk_your_key_here

Authentication

All API requests require the header:

Authorization: Bearer $POSTHERO_API_KEY

Base URL:

https://server.posthero.ai/api/v1

Supported Platforms

LinkedIn, Twitter/X, Instagram, Facebook, YouTube, TikTok, Threads, Bluesky

Character Limits

PlatformLimit
Twitter/X280 per tweet
Bluesky300 per post
Threads500 per post
LinkedIn3000
Instagram2200
Facebook63206
TikTok2200 (caption)
YouTube5000 (description)

Workflow

When the user asks to create or schedule a post:

  1. Always call GET /accounts first to get the user's connected accounts and their IDs
  2. Match the user's requested platform(s) to the account IDs returned
  3. If the user doesn't specify a platform, ask which one(s) they want
  4. If the user wants to schedule, convert their time to ISO 8601 UTC format
  5. Create the post with the appropriate parameters

When the user asks about analytics or post performance:

  1. Call the analytics endpoints with the appropriate platform
  2. Present the data in a clear, readable format

API Reference

GET /accounts

List all connected social media accounts. Always call this first before creating posts.

curl -H "Authorization: Bearer $POSTHERO_API_KEY" \
  https://server.posthero.ai/api/v1/accounts

Response:

{
  "success": true,
  "data": [
    {
      "id": "abc123",
      "platform": "linkedin",
      "name": "John Doe",
      "avatar": "https://...",
      "type": "personal"
    },
    {
      "id": "def456",
      "platform": "twitter",
      "name": "@johndoe",
      "avatar": "https://..."
    }
  ]
}

Use the

id
field as
accountId
when creating posts.


POST /posts

Create a post. Can be a draft, scheduled, or published immediately.

curl -X POST \
  -H "Authorization: Bearer $POSTHERO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "My post content here...",
    "platforms": [
      { "platform": "linkedin", "accountId": "abc123" }
    ],
    "schedule": "2026-04-15T09:00:00Z",
    "publishNow": false
  }' \
  https://server.posthero.ai/api/v1/posts

Request body:

FieldTypeRequiredDescription
text
stringYesThe post content
platforms
arrayYesArray of
{ platform, accountId }
objects
schedule
stringNoISO 8601 UTC datetime. Omit for draft
publishNow
booleanNoSet
true
to publish immediately
isThread
booleanNoSet
true
for threads. Separate posts with
\n\n
in text
platformContent
objectNoPer-platform text overrides (see below)
media
objectNoMedia attachments (see below)

Behavior:

  • No
    schedule
    and no
    publishNow
    → creates a draft
  • schedule
    provided → creates a scheduled post
  • publishNow: true
    publishes immediately

Platform content overrides (optional per-platform text):

{
  "platformContent": {
    "twitter": { "text": "Short tweet version" },
    "linkedin": { "text": "Longer LinkedIn version with #hashtags" },
    "bluesky": { "text": "Bluesky-specific text" },
    "threads": { "text": "Threads version" },
    "facebook": { "text": "Facebook version" },
    "instagram": {
      "text": "Instagram caption",
      "contentType": "feed"
    },
    "youtube": {
      "text": "Video description",
      "title": "My Video Title",
      "tags": ["tag1", "tag2"],
      "privacy": "public",
      "videoType": "long"
    },
    "tiktok": {
      "text": "TikTok caption",
      "privacyLevel": "PUBLIC_TO_EVERYONE",
      "allowComments": true,
      "allowDuet": true,
      "allowStitch": true
    }
  }
}

Media attachments (optional):

{
  "media": {
    "images": ["https://s3-url-1", "https://s3-url-2"],
    "video": "https://s3-video-url",
    "carousel": "https://s3-pdf-url"
  }
}

Use URLs returned by the media upload endpoint. Up to 4 images, or 1 video, or 1 carousel PDF.

Threads: Set

isThread: true
and separate each post with
\n\n
(double line break) in the text. Works for Twitter (280 chars/tweet), Bluesky (300 chars/post), and Threads (500 chars/post).

Response:

{
  "success": true,
  "data": {
    "id": "post_abc123",
    "status": "scheduled",
    "text": "My post content here...",
    "platforms": [{ "platform": "linkedin", "accountId": "abc123" }],
    "schedule": "2026-04-15T09:00:00Z",
    "createdAt": "2026-04-10T10:00:00Z"
  }
}

GET /posts

List posts with optional filters.

curl -H "Authorization: Bearer $POSTHERO_API_KEY" \
  "https://server.posthero.ai/api/v1/posts?status=scheduled&platform=linkedin&page=1&limit=20"

Query parameters:

ParamDescription
status
Filter:
draft
,
scheduled
,
published
,
failed
platform
Filter:
linkedin
,
twitter
,
instagram
,
facebook
,
youtube
,
tiktok
,
threads
,
bluesky
page
Page number (default 1)
limit
Posts per page (default 20, max 100)

Response:

{
  "success": true,
  "data": {
    "posts": [
      {
        "id": "post_abc123",
        "text": "My post content...",
        "status": "published",
        "platforms": [
          {
            "platform": "linkedin",
            "accountId": "abc123",
            "status": "published",
            "postId": "urn:li:share:123456",
            "postUrl": "https://linkedin.com/feed/update/..."
          }
        ],
        "schedule": null,
        "publishedAt": "2026-03-15T14:00:00Z",
        "createdAt": "2026-03-10T10:00:00Z"
      }
    ],
    "pagination": {
      "page": 1,
      "limit": 20,
      "total": 45,
      "hasMore": true
    }
  }
}

GET /posts/:id

Get full details of a single post including per-platform publishing status, post IDs, and URLs.

curl -H "Authorization: Bearer $POSTHERO_API_KEY" \
  https://server.posthero.ai/api/v1/posts/post_abc123

PATCH /posts/:id

Update a draft or scheduled post. Cannot update already-published posts.

curl -X PATCH \
  -H "Authorization: Bearer $POSTHERO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Updated content",
    "schedule": "2026-04-16T10:00:00Z"
  }' \
  https://server.posthero.ai/api/v1/posts/post_abc123

All fields are optional:

text
,
schedule
,
platforms
,
platformContent
,
media
.


DELETE /posts/:id

Delete a post from PostHero. Works for any status (draft, scheduled, published). Does NOT remove it from the social media platform.

curl -X DELETE \
  -H "Authorization: Bearer $POSTHERO_API_KEY" \
  https://server.posthero.ai/api/v1/posts/post_abc123

POST /posts/:id/publish

Immediately publish a draft or scheduled post.

curl -X POST \
  -H "Authorization: Bearer $POSTHERO_API_KEY" \
  https://server.posthero.ai/api/v1/posts/post_abc123/publish

Response:

{
  "success": true,
  "data": {
    "id": "post_abc123",
    "status": "published",
    "results": [
      {
        "platform": "linkedin",
        "status": "published",
        "postId": "urn:li:share:123456",
        "postUrl": "https://linkedin.com/feed/update/..."
      },
      {
        "platform": "twitter",
        "status": "published",
        "postId": "1234567890",
        "postUrl": "https://x.com/user/status/1234567890"
      }
    ]
  }
}

POST /media/upload

Upload an image, video, or carousel PDF. Returns an S3 URL to use in

media
when creating posts.

curl -X POST \
  -H "Authorization: Bearer $POSTHERO_API_KEY" \
  -F "file=@image.jpg" \
  https://server.posthero.ai/api/v1/media/upload

Response:

{
  "success": true,
  "data": {
    "url": "https://s3.amazonaws.com/...",
    "type": "image",
    "size": 245000,
    "mimeType": "image/png"
  }
}

GET /analytics/summary

Get aggregated analytics for a platform.

curl -H "Authorization: Bearer $POSTHERO_API_KEY" \
  "https://server.posthero.ai/api/v1/analytics/summary?platform=threads"

Query parameters:

ParamRequiredDescription
platform
Yes
twitter
,
threads
,
instagram
,
tiktok
,
youtube
accountId
NoFilter by specific account
start
NoStart date (YYYY-MM-DD)
end
NoEnd date (YYYY-MM-DD)

GET /analytics/top

Get top-performing posts ranked by a metric.

curl -H "Authorization: Bearer $POSTHERO_API_KEY" \
  "https://server.posthero.ai/api/v1/analytics/top?platform=threads&metric=likes&limit=5"

Query parameters:

ParamRequiredDescription
platform
Yes
twitter
,
threads
,
instagram
,
tiktok
,
youtube
metric
No
likes
,
impressions
,
comments
,
saves
,
watchMinutes
limit
NoNumber of posts (default 10)
start
NoStart date (YYYY-MM-DD)
end
NoEnd date (YYYY-MM-DD)

GET /analytics/posts

Get paginated post analytics.

curl -H "Authorization: Bearer $POSTHERO_API_KEY" \
  "https://server.posthero.ai/api/v1/analytics/posts?platform=threads&sortBy=likes&limit=20"

GET /analytics/follower-growth

Get follower count and growth delta.

curl -H "Authorization: Bearer $POSTHERO_API_KEY" \
  "https://server.posthero.ai/api/v1/analytics/follower-growth?platform=threads&account=abc123"

Error Handling

All errors return:

{
  "success": false,
  "error": "Human-readable error message",
  "code": "MACHINE_READABLE_CODE"
}
CodeHTTPDescription
UNAUTHORIZED
401Missing or invalid API key
FORBIDDEN
403Plan doesn't include API
NOT_FOUND
404Resource not found
VALIDATION_ERROR
400Invalid request body
ACCOUNT_NOT_FOUND
400Social account not found or not owned by user
RATE_LIMITED
429Too many API requests
PUBLISH_FAILED
500Publishing failed on one or more platforms

Rate Limits

  • 60 requests per minute
  • 100 posts created per month (API plan)
  • Media uploads: 200 per month

Response headers on every request:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1710500000

Important Notes

  • Always call GET /accounts first to get account IDs before creating posts
  • Times must be ISO 8601 UTC format (e.g.
    2026-04-15T09:00:00Z
    )
  • When the user says a time like "tomorrow at 9am", convert to UTC based on context
  • For cross-posting to multiple platforms, include all platform/accountId pairs in the
    platforms
    array
  • Thread mode uses
    \n\n
    as separator — respect per-platform character limits
  • Media URLs must come from the /media/upload endpoint (S3 URLs)
  • DELETE only removes from PostHero, not from the social media platform