Server definition
- Hash
- sha256:392f76ff50a175500dd42cb5a8ec4ec2f36854b1e90c8d4e55fa6d3c6a6fb99c
- What it is
- What a remote MCP server returned when asked what it offers: 14 tools
The blob, as servednamed by its sha256
{
"instructions": "twitr.sh is a pay-per-call X/Twitter API: reads, search, timelines, bulk extractions, real-time monitors with webhook delivery, and posting through a connected X account. Calls without a payment credential return error -32042 with USDC terms for x402 (Base/Solana) and MPP (Tempo); pass the credential in params._meta['org.paymentauth/credential']. Alternatively send the HTTP header `Authorization: Bearer tw_live_…` (an API key from https://twitr.sh/dashboard) and calls are charged to that account's prepaid USD balance instead. Volume tools require resultsLimit (1-10000) and bill per returned item. Resource-creating tools (extractions, monitors, draws, writes) require an idempotency key in params._meta['org.paymentauth/idempotencyKey'] — retries replay instead of re-charging. Monitors are prepaid by the hour and need a recoverable wallet (Base or Tempo, not Solana). Writes act only through X accounts the paying wallet has connected via POST /api/x-accounts/start (returns a connect_url the user opens themselves — never collect X credentials). Full playbook: https://twitr.sh/skill.md — agent guide: https://twitr.sh/llms.txt",
"tools": [
{
"description": "Read an X/Twitter Community: profile info, member and moderator rosters, the community's tweets, or keyword search inside the community. Fixed price for info; billed per item for rosters, tweets, and search.\n\nGuidance: kind=info (fixed price) or members|moderators|tweets|search (per-item — resultsLimit MANDATORY). id = community ID. search additionally requires q.",
"inputSchema": {
"allOf": [
{
"if": {
"properties": {
"kind": {
"const": "search"
}
}
},
"then": {
"required": [
"q"
]
}
}
],
"properties": {
"id": {
"description": "Community ID.",
"type": "string"
},
"kind": {
"description": "What to read.",
"enum": [
"info",
"members",
"moderators",
"tweets",
"search"
],
"type": "string"
},
"q": {
"description": "search: query within the community.",
"type": "string"
},
"resultsLimit": {
"description": "Mandatory for members/moderators/tweets/search: max items, billed per item.",
"maximum": 10000,
"minimum": 1,
"type": "integer"
}
},
"required": [
"kind",
"id"
],
"type": "object"
},
"name": "x_communities",
"outputSchema": null
},
{
"description": "Manage X/Twitter Communities as a connected account: create a new community, join or leave an existing one, or delete a community you own.\n\nGuidance: PREREQUISITE: connect an X account. Acts as a handle THIS wallet owns. action=create (name, optional description) | join|leave (community_id) | delete (community_id + community_name confirmation). account required. Payment settles before the action; Idempotency-Key required.",
"inputSchema": {
"properties": {
"account": {
"description": "A connected X handle owned by this wallet (no @).",
"type": "string"
},
"action": {
"description": "Which community action.",
"enum": [
"create",
"join",
"leave",
"delete"
],
"type": "string"
},
"community_id": {
"description": "join|leave|delete: the community ID.",
"type": "string"
},
"community_name": {
"description": "delete: the community name, as confirmation.",
"type": "string"
},
"description": {
"description": "create: optional community description.",
"type": "string"
},
"name": {
"description": "create: the community name.",
"type": "string"
}
},
"required": [
"action",
"account"
],
"type": "object"
},
"name": "x_community",
"outputSchema": null
},
{
"description": "Draft tweets with AI: generate variants from a topic and goal, refine an existing draft, or score a draft for likely engagement — with tone, call-to-action, and style-matching options. Flat sub-cent price per step.\n\nGuidance: step=generate (topic + goal required; optional tone/styleUsername/additionalContext/callToAction/mediaType/hasLink/hasMedia), refine (draft required), or score (draft required). Returns text variants with scores and suggestions. Flat floor price per call.",
"inputSchema": {
"properties": {
"additionalContext": {
"type": "string"
},
"callToAction": {
"type": "string"
},
"draft": {
"type": "string"
},
"goal": {
"type": "string"
},
"hasLink": {
"type": "boolean"
},
"hasMedia": {
"type": "boolean"
},
"mediaType": {
"type": "string"
},
"step": {
"description": "Composer step.",
"enum": [
"generate",
"refine",
"score"
],
"type": "string"
},
"styleUsername": {
"type": "string"
},
"tone": {
"type": "string"
},
"topic": {
"type": "string"
}
},
"required": [
"step"
],
"type": "object"
},
"name": "x_compose",
"outputSchema": null
},
{
"description": "Run a provably fair giveaway on X/Twitter: pick crypto-random winners from a tweet's replies, with retweet, follow, hashtag, keyword, minimum-follower, and account-age conditions. Fixed price set upfront from your estimated entry count.\n\nGuidance: tweetUrl required. Optional: winnerCount (default 1), backupCount, uniqueAuthorsOnly, mustRetweet, mustFollowUsername, filterMinFollowers, filterAccountAgeDays, filterLanguage, requiredHashtags/Keywords/Mentions. Pricing is fixed upfront from the estimatedEntries you set (default 1000, max 10000) — set it near the tweet's reply count; that number is enforced as a hard cap. Payment settles before the draw runs, so pay only when you intend to run it; a failed draw does not auto-refund (contact support). Idempotency-Key header required — retries with the same key replay the original result instead of re-charging.",
"inputSchema": {
"properties": {
"backupCount": {
"type": "integer"
},
"estimatedEntries": {
"description": "Expected replies inspected — drives the fixed price (default 1000).",
"maximum": 10000,
"minimum": 1,
"type": "integer"
},
"filterAccountAgeDays": {
"type": "integer"
},
"filterLanguage": {
"type": "string"
},
"filterMinFollowers": {
"type": "integer"
},
"mustFollowUsername": {
"type": "string"
},
"mustRetweet": {
"type": "boolean"
},
"requiredHashtags": {
"items": {
"type": "string"
},
"type": "array"
},
"requiredKeywords": {
"items": {
"type": "string"
},
"type": "array"
},
"requiredMentions": {
"items": {
"type": "string"
},
"type": "array"
},
"tweetUrl": {
"description": "Full tweet URL (https://x.com/user/status/ID).",
"type": "string"
},
"uniqueAuthorsOnly": {
"type": "boolean"
},
"winnerCount": {
"minimum": 1,
"type": "integer"
}
},
"required": [
"tweetUrl"
],
"type": "object"
},
"name": "x_draws",
"outputSchema": null
},
{
"description": "Bulk-export X/Twitter data as downloadable datasets: followers, following, repliers, quoters, reposters, likers, mentions, full threads, list and community members, spaces, or people/tweet search results — 23 extractors. Runs async: you get a claim check immediately and poll a free status URL for the download link. Billed per result.\n\nGuidance: tool selects the extractor (23 options). Provide the matching target: targetTweetId (reply/repost/quote/thread/article/favoriters extractors), targetUsername (follower/following/verified/post/mention/likes/media), targetCommunityId, targetListId, targetSpaceId, or searchQuery (people_search, tweet_search_extractor). resultsLimit is MANDATORY — billed per result (article_extractor bills 5× per result). Runs ASYNC: the response is a claim check {snapshot_id, status_url}; poll status_url (free, SIWX) until status=ready for the download link. Idempotency-Key header is required so retries reuse the same job.",
"inputSchema": {
"properties": {
"language": {
"type": "string"
},
"mediaType": {
"enum": [
"images",
"videos",
"gifs",
"media"
],
"type": "string"
},
"minFaves": {
"type": "integer"
},
"resultsLimit": {
"description": "MANDATORY: max results extracted, billed per result.",
"maximum": 10000,
"minimum": 1,
"type": "integer"
},
"searchQuery": {
"type": "string"
},
"sinceDate": {
"type": "string"
},
"targetCommunityId": {
"type": "string"
},
"targetListId": {
"type": "string"
},
"targetSpaceId": {
"type": "string"
},
"targetTweetId": {
"type": "string"
},
"targetUsername": {
"type": "string"
},
"tool": {
"description": "Which extractor to run.",
"enum": [
"follower_explorer",
"following_explorer",
"verified_follower_explorer",
"post_extractor",
"reply_extractor",
"repost_extractor",
"quote_extractor",
"thread_extractor",
"article_extractor",
"favoriters",
"mention_extractor",
"user_likes",
"user_media",
"community_extractor",
"community_moderator_explorer",
"community_post_extractor",
"community_search",
"list_member_extractor",
"list_post_extractor",
"list_follower_explorer",
"space_explorer",
"people_search",
"tweet_search_extractor"
],
"type": "string"
},
"untilDate": {
"type": "string"
},
"verifiedOnly": {
"type": "boolean"
}
},
"required": [
"tool",
"resultsLimit"
],
"type": "object"
},
"name": "x_extract",
"outputSchema": null
},
{
"description": "Read a connected X/Twitter account's private surfaces: bookmarks and bookmark folders, notifications, and DM history. Billed per item returned; readable only for handles this wallet connected.\n\nGuidance: PREREQUISITE: connect an X account (see /api/x-accounts/start). Reads act AS that account, so you can only read the inbox of a handle THIS wallet connected. action=bookmarks (optional folderId) | bookmark_folders | notifications (optional type) | dm_history (target_user_id required). bookmarks/notifications/dm_history are billed per item — set resultsLimit (1–10000). account (the connected handle) is required.",
"inputSchema": {
"properties": {
"account": {
"description": "A connected X handle owned by this wallet (no @).",
"type": "string"
},
"action": {
"description": "Which inbox read to run.",
"enum": [
"bookmarks",
"bookmark_folders",
"notifications",
"dm_history"
],
"type": "string"
},
"folderId": {
"description": "bookmarks: optional folder to read.",
"type": "string"
},
"maxId": {
"description": "dm_history: paginate before this message id.",
"type": "string"
},
"resultsLimit": {
"description": "Max items to return (billed per item); ignored for bookmark_folders.",
"maximum": 10000,
"minimum": 1,
"type": "integer"
},
"target_user_id": {
"description": "dm_history: the other party's user id.",
"type": "string"
},
"type": {
"description": "notifications: optional filter (e.g. mentions).",
"type": "string"
}
},
"required": [
"action",
"account"
],
"type": "object"
},
"name": "x_inbox",
"outputSchema": null
},
{
"description": "Read an X/Twitter List: its combined tweet timeline, its member roster, or its followers. Billed per item returned. Useful for following a curated set of accounts as one feed.\n\nGuidance: kind=tweets|members|followers; id = list ID. resultsLimit is MANDATORY — billed per item returned. tweets supports sinceTime/untilTime and includeReplies.",
"inputSchema": {
"properties": {
"id": {
"description": "List ID.",
"type": "string"
},
"includeReplies": {
"type": "boolean"
},
"kind": {
"description": "What to read from the list.",
"enum": [
"tweets",
"members",
"followers"
],
"type": "string"
},
"resultsLimit": {
"description": "MANDATORY: max items returned, billed per item.",
"maximum": 10000,
"minimum": 1,
"type": "integer"
},
"sinceTime": {
"type": "string"
},
"untilTime": {
"type": "string"
}
},
"required": [
"kind",
"id",
"resultsLimit"
],
"type": "object"
},
"name": "x_lists",
"outputSchema": null
},
{
"description": "Watch an X/Twitter account or keyword query in real time: new tweets, replies, quotes, mentions, hashtags, and profile changes, delivered to your agent by free polling or HMAC-signed webhooks. Prepaid by the hour with a hard stop at expiry — no open-ended billing. The way to track a brand, competitor, or topic without re-polling paid reads.\n\nGuidance: action=create needs username (account monitor, e.g. \"vercel\") OR query (keyword monitor, X search syntax, ≤512 chars), optional eventTypes — 21 available: post events (tweet.new, .reply, .retweet, .quote, .media, .link, .poll, .mention, .hashtag, .longform) for any monitor, plus profile-change events (profile.avatar/banner/name/username/bio/location/url/verified/protected/pinned_tweet/unavailable.changed) for ACCOUNT monitors only; default all applicable — and hours (1–168, default 1). action=extend needs monitorId + hours; hours append to the current expiry (total prepaid window ≤ 720h). Extend at least 5 minutes BEFORE expiry — extends inside the final 5 minutes are refused (unpaid) to keep settlement from racing the expiry teardown. PREPAID: the monitor stops and is removed at expires_at unless extended — no open-ended billing; early deletion does not refund remaining hours. Idempotency-Key header REQUIRED — retries replay the original monitor instead of re-charging (on the MCP door, retries are protected by single-use payment credentials instead). Pay with USDC on Base (x402) or Tempo (MPP); Solana is not offered for monitors (stateful resources need a recoverable owner wallet). After creation: poll events at /api/monitors/{id}/events (free — SIWX sign-in with the paying wallet; do NOT poll in a tight loop) or register an HTTPS webhook once at /api/webhooks to push signed events straight to your AI agent (Claude, OpenClaw, Hermes, or any endpoint) in real time. Manage monitors at /api/monitors (SIWX).",
"inputSchema": {
"properties": {
"action": {
"description": "Create a new monitor or extend an existing one.",
"enum": [
"create",
"extend"
],
"type": "string"
},
"eventTypes": {
"description": "Event types to receive (default: all applicable). Post events (tweet.*) work for any monitor; profile-change events (profile.*.changed) apply to ACCOUNT monitors only.",
"items": {
"enum": [
"tweet.new",
"tweet.reply",
"tweet.retweet",
"tweet.quote",
"tweet.media",
"tweet.link",
"tweet.poll",
"tweet.mention",
"tweet.hashtag",
"tweet.longform",
"profile.avatar.changed",
"profile.banner.changed",
"profile.name.changed",
"profile.username.changed",
"profile.bio.changed",
"profile.location.changed",
"profile.url.changed",
"profile.verified.changed",
"profile.protected.changed",
"profile.pinned_tweet.changed",
"profile.unavailable.changed"
],
"type": "string"
},
"type": "array"
},
"hours": {
"description": "Prepaid hours to purchase (default 1).",
"maximum": 168,
"minimum": 1,
"type": "integer"
},
"monitorId": {
"description": "Monitor to extend (extend only).",
"type": "string"
},
"query": {
"description": "X search query to monitor (create, type=keyword).",
"maxLength": 512,
"type": "string"
},
"type": {
"description": "Monitor kind (create). Inferred from username/query when omitted.",
"enum": [
"account",
"keyword"
],
"type": "string"
},
"username": {
"description": "X handle to monitor, without @ (create, type=account).",
"type": "string"
}
},
"required": [
"action"
],
"type": "object"
},
"name": "x_monitor",
"outputSchema": null
},
{
"description": "Edit a connected X/Twitter account's profile: display name, bio, location, website link, avatar image, and banner image. Acts only on handles this wallet connected.\n\nGuidance: PREREQUISITE: connect an X account. Acts as a handle THIS wallet owns. action=update_profile (any of name, description, location, url) | set_avatar (media_url) | set_banner (media_url). account required. Payment settles before the change; Idempotency-Key required.",
"inputSchema": {
"properties": {
"account": {
"description": "A connected X handle owned by this wallet (no @).",
"type": "string"
},
"action": {
"description": "Which profile edit to make.",
"enum": [
"update_profile",
"set_avatar",
"set_banner"
],
"type": "string"
},
"description": {
"description": "update_profile: new bio.",
"type": "string"
},
"location": {
"description": "update_profile: new location.",
"type": "string"
},
"media_url": {
"description": "set_avatar|set_banner: public image URL.",
"type": "string"
},
"name": {
"description": "update_profile: new display name.",
"type": "string"
},
"url": {
"description": "update_profile: new website URL.",
"type": "string"
}
},
"required": [
"action",
"account"
],
"type": "object"
},
"name": "x_profile",
"outputSchema": null
},
{
"description": "Trending topics and breaking stories across tech, dev, science, business, culture, politics, and entertainment — aggregated from multiple public sources with regional and time-window filters. Flat sub-cent price per call; the cheap first stop for what is happening right now.\n\nGuidance: Optional filters: category, region, hours (lookback), limit, source. Use report.next_cursor via `after` for the next page. Flat floor price per call.",
"inputSchema": {
"properties": {
"after": {
"description": "Pagination cursor.",
"type": "string"
},
"category": {
"description": "Topic category filter.",
"enum": [
"general",
"tech",
"dev",
"science",
"culture",
"politics",
"business",
"entertainment"
],
"type": "string"
},
"hours": {
"type": "integer"
},
"limit": {
"type": "integer"
},
"region": {
"type": "string"
},
"source": {
"description": "Trend source filter.",
"enum": [
"github",
"google_trends",
"hacker_news",
"polymarket",
"reddit",
"trustmrr",
"wikipedia"
],
"type": "string"
}
},
"type": "object"
},
"name": "x_radar",
"outputSchema": null
},
{
"description": "Read live X/Twitter data: look up a single tweet or user profile, batch-read up to 100 tweets or users at once, check whether one account follows another, fetch trending topics by region, extract a long-form article, or download tweet media. Pay per call in USDC — no API key, no signup; failed calls are never charged.\n\nGuidance: resource=get-tweet|get-user (id), batch-tweets|batch-users (ids array, ≤100), check-follower (source+target usernames), trends (optional woeid/count), article (tweet id), followers-you-know (id + mandatory resultsLimit), download-media (id or ids ≤50 — returns media file URLs on THIS origin; links live 7 days). Fixed-price per call/id except followers-you-know which is per-result.",
"inputSchema": {
"allOf": [
{
"if": {
"properties": {
"resource": {
"const": "followers-you-know"
}
}
},
"then": {
"required": [
"resultsLimit"
]
}
}
],
"properties": {
"count": {
"description": "trends: number of trends to return.",
"type": "integer"
},
"id": {
"description": "Tweet ID, user ID, or username (depends on resource).",
"type": "string"
},
"ids": {
"description": "batch-tweets|batch-users: up to 100 tweet IDs or user IDs/usernames.",
"items": {
"type": "string"
},
"type": "array"
},
"resource": {
"description": "Which read operation to run.",
"enum": [
"get-tweet",
"get-user",
"batch-tweets",
"batch-users",
"check-follower",
"trends",
"article",
"followers-you-know",
"download-media"
],
"type": "string"
},
"resultsLimit": {
"description": "Mandatory for followers-you-know: max results, billed per result.",
"maximum": 10000,
"minimum": 1,
"type": "integer"
},
"source": {
"description": "check-follower: source username.",
"type": "string"
},
"target": {
"description": "check-follower: target username.",
"type": "string"
},
"woeid": {
"description": "trends: region WOEID (default 1 = worldwide).",
"type": "integer"
}
},
"required": [
"resource"
],
"type": "object"
},
"name": "x_read",
"outputSchema": null
},
{
"description": "Search X/Twitter tweets with the full operator set — keyword, exact phrase, from-user, language, date range, media type, minimum likes/retweets, verified-only — or search user profiles by keyword. Billed per tweet returned against your resultsLimit cap. Built for tracking what people say about a topic, brand, or ticker in real time.\n\nGuidance: type=search-tweets (default): q required, resultsLimit MANDATORY (billed per tweet returned). Supports the full filter set: fromUser, language, sinceDate/untilDate, mediaType, minFaves, verifiedOnly, exactPhrase, excludeWords, advancedQuery, and more. type=search-users: q required; returns one results page per call — follow report.next_cursor for the next page (each page is a separate paid call).",
"inputSchema": {
"allOf": [
{
"else": {
"required": [
"resultsLimit"
]
},
"if": {
"properties": {
"type": {
"const": "search-users"
}
}
},
"then": {}
}
],
"properties": {
"advancedQuery": {
"description": "Raw X search operator string appended to q.",
"type": "string"
},
"cursor": {
"description": "search-users: pagination cursor from a previous call's report.next_cursor.",
"type": "string"
},
"exactPhrase": {
"type": "string"
},
"excludeWords": {
"type": "string"
},
"fromUser": {
"type": "string"
},
"language": {
"type": "string"
},
"mediaType": {
"enum": [
"images",
"videos",
"gifs",
"media"
],
"type": "string"
},
"minFaves": {
"type": "integer"
},
"minReplies": {
"type": "integer"
},
"minRetweets": {
"type": "integer"
},
"q": {
"description": "Search query (X operator syntax supported for tweets).",
"type": "string"
},
"resultsLimit": {
"description": "search-tweets: MANDATORY max tweets returned, billed per tweet.",
"maximum": 10000,
"minimum": 1,
"type": "integer"
},
"sinceDate": {
"description": "YYYY-MM-DD",
"type": "string"
},
"type": {
"description": "Search tweets (default) or users.",
"enum": [
"search-tweets",
"search-users"
],
"type": "string"
},
"untilDate": {
"description": "YYYY-MM-DD",
"type": "string"
},
"verifiedOnly": {
"type": "boolean"
}
},
"required": [
"q"
],
"type": "object"
},
"name": "x_search",
"outputSchema": null
},
{
"description": "Fetch a user's X/Twitter timeline — their tweets, replies, likes, media posts, or mentions — plus follower and following lists, and per-tweet engagement lists (who replied, quoted, retweeted, or favorited). Billed per item returned. The building block for monitoring what an account posts or ranking accounts by activity.\n\nGuidance: kind selects the timeline: user-tweets|user-replies|user-likes|user-media|user-mentions|followers|following|verified-followers (id = user) or tweet-replies|tweet-quotes|tweet-thread|tweet-favoriters|tweet-retweeters (id = tweet). resultsLimit is MANDATORY — billed per item returned. Search-operator filters (fromUser, language, mediaType, minFaves, …) apply to tweet timelines.",
"inputSchema": {
"properties": {
"id": {
"description": "User ID/username or tweet ID (depends on kind).",
"type": "string"
},
"includeParentTweet": {
"type": "boolean"
},
"includeReplies": {
"type": "boolean"
},
"kind": {
"description": "Which timeline to fetch.",
"enum": [
"user-tweets",
"user-replies",
"user-likes",
"user-media",
"user-mentions",
"followers",
"following",
"verified-followers",
"tweet-replies",
"tweet-quotes",
"tweet-thread",
"tweet-favoriters",
"tweet-retweeters"
],
"type": "string"
},
"language": {
"type": "string"
},
"mediaType": {
"enum": [
"images",
"videos",
"gifs",
"media"
],
"type": "string"
},
"minFaves": {
"type": "integer"
},
"resultsLimit": {
"description": "MANDATORY: max items returned, billed per item.",
"maximum": 10000,
"minimum": 1,
"type": "integer"
},
"verifiedOnly": {
"type": "boolean"
}
},
"required": [
"kind",
"id",
"resultsLimit"
],
"type": "object"
},
"name": "x_timeline",
"outputSchema": null
},
{
"description": "Act on X/Twitter through an account you connect: post a tweet, reply, like, retweet, follow or unfollow, send a DM, delete a tweet, remove a follower, or upload media. Ownership is checked server-side — an agent can only write as a handle its own wallet connected.\n\nGuidance: PREREQUISITE: connect an X account first — POST /api/x-accounts/start (free, SIWX) with {username} only; it returns a one-time connect_url the USER opens in their own browser to sign in there. Never ask the user for their X password, email, or 2FA secret. Poll GET /api/x-accounts until the handle shows linked, then reference it in `account`. Actions: post (text) | reply (text + reply_to_tweet_id) | like|unlike|retweet|unretweet|delete_tweet (target_tweet_id) | follow|unfollow (target_user_id — the NUMERIC user id, get it from x_read get-user) | remove_follower (target_user_id of the follower) | send_dm (target_user_id + text) | upload_media (media_url → returns media_id). You can only write as a handle THIS wallet connected (checked server-side; the input account is not trusted). Payment settles before the action runs and is non-refundable; a write may return status=pending_confirmation with an actionId to poll — do NOT resend. Idempotency-Key header is required so a retry replays the original result instead of acting twice.",
"inputSchema": {
"properties": {
"account": {
"description": "A connected X handle owned by this wallet (no @).",
"type": "string"
},
"action": {
"description": "Which write to perform.",
"enum": [
"post",
"reply",
"like",
"unlike",
"retweet",
"unretweet",
"follow",
"unfollow",
"delete_tweet",
"send_dm",
"remove_follower",
"upload_media"
],
"type": "string"
},
"community_id": {
"description": "post: optional community to post into.",
"type": "string"
},
"is_note_tweet": {
"description": "post: long-form note tweet.",
"type": "boolean"
},
"media_ids": {
"description": "send_dm: optional uploaded media ids to attach.",
"items": {
"type": "string"
},
"type": "array"
},
"media_url": {
"description": "upload_media: public URL of the file to upload; returns a media_id.",
"type": "string"
},
"reply_to_tweet_id": {
"description": "reply: the tweet being replied to.",
"type": "string"
},
"target_tweet_id": {
"description": "like|unlike|retweet|unretweet|delete_tweet: the target tweet ID.",
"type": "string"
},
"target_user_id": {
"description": "follow|unfollow|send_dm|remove_follower: the numeric X user id of the target (not the @handle). Get it from x_read get-user.",
"type": "string"
},
"text": {
"description": "post|reply|send_dm: the message body.",
"type": "string"
}
},
"required": [
"action",
"account"
],
"type": "object"
},
"name": "x_write",
"outputSchema": null
}
]
}Verify it yourself
curl -s https://api.teppi.xyz/v1/evidence/sha256:392f76ff50a175500dd42cb5a8ec4ec2f36854b1e90c8d4e55fa6d3c6a6fb99c | sha256sum