Install
openclaw skills install adaptlypostSchedule and manage social media posts across Instagram, X (Twitter), Bluesky, TikTok, Threads, LinkedIn, Facebook, Pinterest, and YouTube using the AdaptlyP...
openclaw skills install adaptlypostSchedule social media posts across 9 platforms from one API. SaaS — no self-hosting needed.
export ADAPTLYPOST_API_KEY="adaptly_your-token-here"
Base URL: https://post.adaptlypost.com/post/api/v1
Auth header: Authorization: Bearer $ADAPTLYPOST_API_KEY
Posts are public, attributable, and hard to fully retract. Treat every POST /social-posts and POST /upload-urls as a high-impact action.
POST /social-posts, show the user a summary and get an explicit "yes" covering all four items:
displayName/username, not just ID)privacyLevel, YouTube privacyStatus, Instagram postType, etc.
A previous "yes" does not authorize a new post. Re-confirm each one.saveAsDraft: true and let them review in the AdaptlyPost UI before publishing./upload-urls are stored at a public URL that exists from the moment of upload — before the post goes live, and even if the post is never created. Before calling /upload-urls:
~/Downloads, ~/Desktop, screenshot folders, etc.) without an explicit per-file "yes".POST /social-posts returns an error or unexpected skippedPlatforms, surface it to the user and ask before retrying — do not loop.curl -s -H "Authorization: Bearer $ADAPTLYPOST_API_KEY" \
https://post.adaptlypost.com/post/api/v1/social-accounts
Returns { "accounts": [{ "id", "platform", "displayName", "username", "avatarUrl" }] }. Save the id — you'll use it as a connection ID when creating posts.
⚠️ Immediate publish is irreversible from the agent's side — once POST /social-posts returns, the content is live on the user's connected accounts. Only call this after the four-item confirmation in Safety rules.
To publish right away, simply omit scheduledAt entirely and do NOT set saveAsDraft:
curl -X POST https://post.adaptlypost.com/post/api/v1/social-posts \
-H "Authorization: Bearer $ADAPTLYPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platforms": ["TWITTER"],
"contentType": "TEXT",
"text": "This goes live right now!",
"timezone": "America/New_York",
"twitterConnectionIds": ["CONNECTION_ID_HERE"]
}'
IMPORTANT: Do NOT set scheduledAt to a time in the near future as a workaround. Omitting scheduledAt is the correct way to publish immediately.
Returns { "postId", "queuedPlatforms", "skippedPlatforms", "isScheduled", "scheduledAt" }.
Important: You must include the correct *ConnectionIds array for each platform in platforms. For example, if posting to Instagram and Twitter, include both instagramConnectionIds and twitterConnectionIds. For Facebook, use pageIds instead.
curl -X POST https://post.adaptlypost.com/post/api/v1/social-posts \
-H "Authorization: Bearer $ADAPTLYPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platforms": ["TWITTER"],
"contentType": "TEXT",
"text": "Your post text here",
"timezone": "America/New_York",
"scheduledAt": "2026-06-15T10:00:00.000Z",
"twitterConnectionIds": ["CONNECTION_ID_HERE"]
}'
Same as scheduling, but set saveAsDraft: true and omit scheduledAt:
curl -X POST https://post.adaptlypost.com/post/api/v1/social-posts \
-H "Authorization: Bearer $ADAPTLYPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platforms": ["INSTAGRAM"],
"contentType": "TEXT",
"text": "Draft post to review later",
"timezone": "Europe/London",
"saveAsDraft": true,
"instagramConnectionIds": ["CONNECTION_ID_HERE"]
}'
⚠️ The publicUrl returned in Step A is publicly reachable as soon as Step B completes — even if you never create the post in Step C. Confirm the exact file path with the user before Step A, and never upload a file the user has not explicitly named.
Step A — Get presigned upload URLs:
curl -X POST https://post.adaptlypost.com/post/api/v1/upload-urls \
-H "Authorization: Bearer $ADAPTLYPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "files": [{ "fileName": "photo.jpg", "mimeType": "image/jpeg" }] }'
Returns { "urls": [{ "fileName", "uploadUrl", "publicUrl", "key", "expiresAt" }] }.
Step B — Upload file to storage:
curl -X PUT "UPLOAD_URL_HERE" \
-H "Content-Type: image/jpeg" \
--data-binary @/path/to/photo.jpg
Step C — Create post with the public URL:
curl -X POST https://post.adaptlypost.com/post/api/v1/social-posts \
-H "Authorization: Bearer $ADAPTLYPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platforms": ["INSTAGRAM"],
"contentType": "IMAGE",
"text": "Post with image!",
"mediaUrls": ["PUBLIC_URL_FROM_STEP_A"],
"timezone": "America/New_York",
"scheduledAt": "2026-06-15T10:00:00.000Z",
"instagramConnectionIds": ["CONNECTION_ID_HERE"]
}'
For video: use mimeType: "video/mp4", contentType: "VIDEO".
For carousel: upload multiple files, include all public URLs in mediaUrls, use contentType: "CAROUSEL".
curl -s -H "Authorization: Bearer $ADAPTLYPOST_API_KEY" \
"https://post.adaptlypost.com/post/api/v1/social-posts?limit=20&offset=0"
Returns { "posts": [...], "total": 25, "hasMore": true }. Use limit (1-100, default 20) and offset (default 0) for pagination.
curl -s -H "Authorization: Bearer $ADAPTLYPOST_API_KEY" \
https://post.adaptlypost.com/post/api/v1/social-posts/POST_ID
Returns full post object with platform-specific status for each target platform.
Include multiple platforms and their connection IDs in a single request:
curl -X POST https://post.adaptlypost.com/post/api/v1/social-posts \
-H "Authorization: Bearer $ADAPTLYPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platforms": ["TWITTER", "BLUESKY", "LINKEDIN"],
"contentType": "TEXT",
"text": "Same post across 3 platforms!",
"timezone": "America/New_York",
"scheduledAt": "2026-06-15T10:00:00.000Z",
"twitterConnectionIds": ["TWITTER_ID"],
"blueskyConnectionIds": ["BLUESKY_ID"],
"linkedinConnectionIds": ["LINKEDIN_ID"]
}'
Override the default text for specific platforms:
curl -X POST https://post.adaptlypost.com/post/api/v1/social-posts \
-H "Authorization: Bearer $ADAPTLYPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platforms": ["TWITTER", "LINKEDIN"],
"contentType": "TEXT",
"text": "Default text for all platforms",
"platformTexts": [
{ "platform": "TWITTER", "text": "Short version for X #shortform" },
{ "platform": "LINKEDIN", "text": "Longer professional version with more detail for LinkedIn audience." }
],
"timezone": "America/New_York",
"scheduledAt": "2026-06-15T10:00:00.000Z",
"twitterConnectionIds": ["TWITTER_ID"],
"linkedinConnectionIds": ["LINKEDIN_ID"]
}'
Pass these as config arrays in the request body. See references/platform-configs.md for full details.
| Platform | Config Field | Key Options |
|---|---|---|
| TikTok | tiktokConfigs | privacyLevel (required), allowComments, allowDuet, allowStitch, sendAsDraft, brandedContent, autoAddMusic |
instagramConfigs | postType (FEED/REEL/STORY) | |
facebookConfigs | postType (FEED/REEL/STORY), videoTitle | |
| YouTube | youtubeConfigs | postType (VIDEO/SHORTS), videoTitle, tags, privacyStatus, madeForKids, playlistId |
pinterestConfigs | boardId (required), title, link | |
| X (Twitter) | — | No config object, uses twitterConnectionIds only |
| Bluesky | — | No config object, uses blueskyConnectionIds only |
| Threads | — | No config object, uses threadsConnectionIds only |
| — | No config object, uses linkedinConnectionIds only |
Example with TikTok config:
curl -X POST https://post.adaptlypost.com/post/api/v1/social-posts \
-H "Authorization: Bearer $ADAPTLYPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platforms": ["TIKTOK"],
"contentType": "VIDEO",
"text": "Check out this clip!",
"mediaUrls": ["https://cdn.adaptlypost.com/social-media-posts/uuid/video.mp4"],
"timezone": "America/New_York",
"scheduledAt": "2026-06-15T18:00:00.000Z",
"tiktokConnectionIds": ["TIKTOK_ID"],
"tiktokConfigs": [{
"connectionId": "TIKTOK_ID",
"privacyLevel": "PUBLIC_TO_EVERYONE",
"allowComments": true,
"allowDuet": false,
"allowStitch": true
}]
}'
| MIME Type | Extension | Use For |
|---|---|---|
image/jpeg | .jpg, .jpeg | Images |
image/png | .png | Images |
image/webp | .webp | Images |
video/mp4 | .mp4 | Videos |
video/quicktime | .mov | Videos |
Upload 1-20 files per request.
| Platform | Images | Video | Carousel |
|---|---|---|---|
| TikTok | Carousels only | MP4/MOV, ≤250MB, 3s-10min | 2-35 images |
| JPEG/PNG | ≤1GB, 3-90s (Reels) | Up to 10 | |
| ≤30MB, JPG/PNG | 1 per post | Up to 10 images | |
| YouTube | — | Shorts ≤3min, H.264 | — |
| Up to 9 | ≤10min | Up to 9 | |
| X (Twitter) | Up to 4 | — | — |
| 2:3 ratio ideal | Supported | 2-5 images | |
| Bluesky | Up to 4 | Not supported | — |
| Threads | Supported | Supported | Up to 10 |
POST /social-posts, show a final summary covering content, platforms (named, not just IDs), timing, and visibility, and wait for an explicit "yes". Re-confirm for every post — prior approval does not carry over.saveAsDraft: true so the user can review in the AdaptlyPost UI before anything goes live.scheduledAt from the request body — do NOT set it to a time in the near future. The API publishes immediately when scheduledAt is absent.scheduledAt to an ISO 8601 timestamp.saveAsDraft: true and omit scheduledAt.timezone field is required on every post creation request.Europe/London, Europe/Berlin, Europe/Paris, America/New_York, America/Chicago, America/Los_Angeles, Asia/Tokyo, Australia/Sydney./social-accounts first to get valid connection IDs for each platform.mediaUrls).scheduledAt must be ISO 8601 and in the future. Omit it when using saveAsDraft: true.twitterConnectionIds, instagramConnectionIds, blueskyConnectionIds, linkedinConnectionIds, tiktokConnectionIds, threadsConnectionIds, pinterestConnectionIds, youtubeConnectionIds. Facebook uses pageIds.privacyLevel — always set it (e.g., PUBLIC_TO_EVERYONE).boardId — there is no way to fetch boards via this API currently, so ask the user which board to use.mediaUrls.platformTexts to customize text per platform when cross-posting.TEXT (no media), IMAGE (single image), VIDEO (single video), CAROUSEL (multiple images/videos).skippedPlatforms in the response — it tells you if any platform was skipped and why.