xpost.to — post to 9 social networks
Post to social media through xpost — draft, schedule, edit and check delivery across X, Instagram, LinkedIn, Facebook, TikTok, YouTube, Threads, Bluesky and Pinterest, with their b…
vladkorzinin
@vladkorzinin
Install
$ openclaw skills install @vladkorzinin/xpostPosting through xpost
xpost is the posting layer between you and the user's social audience. It
holds their connected accounts, their brand rules and, where they have asked
for one, their approval queue. Creating a post sends it: it publishes at
the time given, or straight away when none is — there is no second step that
sends it. A project in copilot mode holds an agent's posts for approval
instead (get_project says which), and the approval route refuses an agent
key in every mode, so a held post moves when a person moves it.
A post made by hand in a browser is invisible to all three, and cannot be tracked, retried or taken down from here. These tools are the route that leaves a record.
Connection
Preferred: the xpost MCP server. If it is connected you have the
tools below and nothing else is needed. If it is not connected, here is how —
no key required:
- Claude Code:
claude mcp add --transport http xpost https://xpost.to/api/mcp, then/mcp→ xpost → sign in. - Cursor / Windsurf / Gemini CLI / VS Code: add
https://xpost.to/api/mcpas an HTTP MCP server; the client opens the sign-in page. - ChatGPT: xpost is in the plugin directory — find it, add it, sign in.
- Claude.ai / Claude Desktop: Settings → Connectors → Add custom connector, paste
https://xpost.to/api/mcp, sign in.
Fallback: the xpost CLI (npx xpost, zero install), when there is no
MCP client — a shell, a script, a headless box. Every command is one route of
the public API and answers with the API's own JSON; a refusal prints the
body and exits 1, so error_code is the machine-readable half. Sign in once
with npx xpost login (a browser opens), or set XPOST_API_KEY where no
browser can. The tool names below map one to one:
npx xpost project # get_project
npx xpost accounts # list_accounts
npx xpost rules <accountId> # get_posting_rules
npx xpost upload ./pic.jpg --alt "…" # upload_media → media id
npx xpost posts create -c "…" -a <account> [-a …] [--media <id>] [--at 2026-10-01T09:00:00+02:00] [--draft] [--config '{"x":{"first_comment":"…"}}']
npx xpost posts list --status pending_approval,rejected
npx xpost posts edit <postId> -c "…" # update_post — answers with a NEW id
npx xpost posts delete <postId>
npx xpost receipt <postId> # get_delivery_receipt
Raw HTTP works too: XPOST_URL (default https://xpost.to) +
Authorization: Bearer $XPOST_API_KEY, spec at $XPOST_URL/api/v1/openapi.json.
The tools
| Do this | Tool |
|---|---|
| Learn the project: timezone, approval mode, signature, guardrails, allowance | get_project |
| See destinations and what each can carry | list_accounts |
| The exact options an account takes (placements, first comment, boards…) | get_posting_rules |
| Attach a file the user gave you (path, URL, or a chat attachment) | upload_media — or create_post with files / media_pending |
| Create one post | create_post |
| Create many | bulk_post |
| Find posts, see verdicts and rejection reasons | list_posts |
| Change words, media, time or options | update_post |
| Remove your own unpublished post | delete_post |
| Where it landed, per account | get_delivery_receipt |
| A destination failed — try it again | retry_delivery |
| Pull a live post down (only when asked) | take_down_post |
| Which accounts need reconnecting | list_connection_issues |
| Test a caption against the rules before writing more | check_guardrails |
| Learn what works | get_post_metrics, get_insights, get_top_posts, get_best_times |
Workflow
get_project, thenlist_accounts. You need account ids, and each account says what it can carry (limits,can). An empty list comes withconnect_messageandconnect_url: nothing can be posted until the person connects an account. Both are written for them to read as they stand — the message is the sentence, the url is where it happens.get_posting_rulesfor the accounts you will use, whenever you set anything beyond a caption. It is the option catalog per ACCOUNT — a key that is absent cannot be used on that account, whatever the platform allows elsewhere. Pinterest answers liveboardswitheligible; a board that is not eligible is refused.- Media. Instagram, TikTok, YouTube and Pinterest require it; stories
and reels do too.
upload_mediatakes a localpath(stdio server only), a publicurl, or base64data. A picture, video or PDF the user attached to the chat goes ON THE POST, two ways:- Your host hands attachments over as file objects (ChatGPT does): pass
them as
filesoncreate_postorupdate_post, in post order. - Otherwise create the post with
media_pending: true. It is held, and the reply carriesupload_urlandupload_curl: if the file is in your environment, that command (YOUR_FILE replaced) lands the picture on the post — nothing passes through a tool argument, so no host asks anyone to allow an opaque payload. Where it cannot be run, the approval card that came back carries a drop zone: the person adds the picture there, straight onto the post, and approves in the same card. Either way nothing comes back to you; the post simply has its picture.list_postsshowsmediaIds. Base64dataonupload_mediais for something you generated, not the user's file. "I've added another photo" therefore needs nothing further — it is already on the post. To add one from the chat,update_postwithfilesoradd_media_ids;media_idsreplaces the set. A PDF is a LinkedIn document post: one PDF, alone, LinkedIn only.
- Your host hands attachments over as file objects (ChatGPT does): pass
them as
create_post.scheduled_atis ISO 8601 with an offset, in the project's timezone (fromget_project); omit it and the post goes out now (or, in copilot mode, as soon as they approve it)."next_slot"hands the time to the project's own posting schedule — it fits "queue it", and any ask with no time behind it whereget_projectshowsqueue.configured: true(itsnext_slotsare what they will get). Refused asno_queue_slotswhere there is no schedule, and a time then has to come from the person.is_draft: truefiles a scratchpad draft — no queue, no approval link; the person sends it from its page. Per-account words and options go inplatform_configurations, keyed by platform:{"x": {"caption": "shorter", "first_comment": "…", "thread": ["…"]}},{"instagram": {"placement": "stories"}}. Every text field — caption, overrides, first comment, thread — runs through the guardrails.- What the answer means.
scheduled— the normal outcome: nothing is holding it.publishesis when it goes out, on the project's clock, and the See post preview link the result carries is the door to it — the post as every destination will draw it, still changeable, still cancellable, and after it lands, still removable.pending_approval— this project holds agent posts. It is waiting on a person, it has not published, and the call has already landed; the same preview link is where they see it.ok: falsewitherror_code— a refusal, as data. Guardrail violations name the rule inviolations[].detail, and the same rules run again on the next attempt, so a caption that meets them is what clears it. A missing plan (publishing_needs_plan) or a missing account comes with amessagewritten for the person.
list_postsis the current state of the queue. Itsfrom/tobound the scheduled time, so "what goes out next week" is one call, soonest first. The person can reject through a link you never see; arejectedrow carriesrejectionReason, which is what to fix. To change anything,update_post— it answers with a new id, and an edit to an approved post goes back into the queue because the approval was for the old words.- After publish time,
get_delivery_receipt. One row per destination, each with its live link or the reason it failed.retry_deliverytakes a failed row;take_down_postis for when the user asks for it, because there is no undo.
Bulk
For a calendar or a CSV, bulk_post (≤100 rows) instead of a loop. Rows are
independent, and the answer is per row: which were created (every row
scheduled, or pending_approval on a project that holds agent posts, is
normal) and which failed, with the reason. Only the failed rows need sending
again. An idempotency_key per row makes a
resend after a timeout answer repeated: true instead of making a second copy.
Learning what works
Before drafting, when there is history: get_top_posts shows what actually
performed — what carries over is angle, length and format, since the captions
belong to those posts — and
get_best_times ranks slots from this workspace's own results. signal is
what that ranking is worth: none or thin means there is too little
history behind it for an hour to mean anything. After a post has been live a while,
get_post_metrics; null means the platform does not report that metric,
not zero, and stories are not reported on by anyone. get_insights for
"how are we doing".
Worth knowing
- Each
create_postis one post. Variations are separate posts, and each of them is sent. - The time that will happen is
publishesin the answer, on the project's clock — a request'sscheduled_atis what was asked for, not what came back. - A guardrail refusal is about the words; a held post is about a person. One is fixed by rewriting, the other by waiting.
- A receipt can be partial — delivered on X, failed on Instagram with its own reason — because each destination is independent.
- Upload plumbing (sandboxes, hosts, slots) is nothing the person can act on; the card asks them for the file itself. What is open to them is the post: a missing caption, the time, the destinations.
Top skills in this category
here.now
@adamludwinhere.now lets agents publish websites and files to live URLs in seconds. Publish HTML, documents, images, PDFs, videos, and static files to live URLs at {slug}.here.now or custom domains. Use when asked to "publish this", "host this", "deploy this", "share this on the web", "make a website", "put this online", "create a webpage", "generate a URL", "build a chatbot", "password protect this site", "make this site private", or "share this site with only certain people". here.now also includes workspaces — shared team accounts where Sites belong to the team and serve at {label}.{workspace}.here.now — use when asked to "publish this to our team workspace", "share this with my team", or "put this in our company workspace". Agents can also buy a domain for a Site through here.now (no markup, DNS and SSL automatic) — use when asked to "buy a domain", "get me a .com for this", or "register a domain".
YouTube
@byungkyuYouTube Data API integration with managed OAuth. Search videos, manage playlists, access channel data, and interact with comments. Use this skill when users want to interact with YouTube. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway). Calls run through the `maton` CLI with OAuth login, or over raw HTTP with a Maton API key where the CLI cannot be installed. Every call is authenticated as the user's connection and reaches only what that connection's authorization allows, which the provider enforces on every request; the endpoints documented here are the ones this skill uses, and any other endpoint of this app needs the user to ask for it by name. Default to read and list calls, and confirm every write or new connection with the user. This file also documents the three constructs that turn a YouTube connection into automation, in the order they are used: the connection (the first step), a hosted function that runs a YouTube action through the Maton SDK, and a trigger that calls that function on a schedule or on an event. Those sections are the platform's own reference text, shared with the api-gateway skill, with YouTube examples; they add no YouTube capability - YouTube is not an event source, a trigger cannot read YouTube data, and the files under `references/<source>/triggers.md` are the platform's event catalogues for the sources Maton offers (time, Calendly, GitHub, Gmail, HubSpot, Linear, Notion, Slack, Stripe).
diagram-generator
@matthewyinGenerate and edit diagrams with the mcp-diagram-generator MCP server. Use this skill for new diagrams, existing .drawio/.mmd/.excalidraw edits, network topology, architecture, flowchart, swimlane, sequence, class, ER, and Excalidraw whiteboard work. Always use this skill when the user asks to draw,
Edge TTS
@i3130002Text-to-speech conversion using node-edge-tts npm package for generating audio from text. Supports multiple voices, languages, speed adjustment, pitch control, and subtitle generation. Use when: (1) User requests audio/voice output with the "tts" trigger or keyword. (2) Content needs to be spoken rather than read (multitasking, accessibility, driving, cooking). (3) User wants a specific voice, speed, pitch, or format for TTS output.
YouTube Transcript
@xthezealotFetch and summarize YouTube video transcripts. Use when asked to summarize, transcribe, or extract content from YouTube videos. Handles transcript fetching via residential IP proxy to bypass YouTube's cloud IP blocks.