---
title: "X/Twitter Write"
method: POST
path: "/api/tools/x_write"
tags: ["Social"]
---

# X/Twitter Write

`POST /api/tools/x_write`

## Request

- Base URL: `https://twitr.sh`
- URL: `https://twitr.sh/api/tools/x_write`
- Auth: none declared. Required headers: `Idempotency-Key`

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.

## Headers

- `Idempotency-Key` string, required

## Request body

- object
  - `action` 'post' | 'reply' | 'like' | 'unlike' | 'retweet' | 'unretweet' | 'follow' | 'unfollow' | 'delete_tweet' | 'send_dm' | 'remove_follower' | 'upload_media', required: Which write to perform.
  - `account` string, required: A connected X handle owned by this wallet (no @).
  - `text` string: post|reply|send_dm: the message body.
  - `reply_to_tweet_id` string: reply: the tweet being replied to.
  - `target_tweet_id` string: like|unlike|retweet|unretweet|delete_tweet: the target tweet ID.
  - `target_user_id` string: follow|unfollow|send_dm|remove_follower: the numeric X user id of the target (not the @handle). Get it from x_read get-user.
  - `media_url` string: upload_media: public URL of the file to upload; returns a media_id.
  - `media_ids` string[]: send_dm: optional uploaded media ids to attach.
  - `community_id` string: post: optional community to post into.
  - `is_note_tweet` boolean: post: long-form note tweet.

## Response `200`

Result dataset.

- object
  - `items` object[], required: Array of returned items. Shape varies per tool — see each tool's documentation.
  - `runId` string: Run ID for debugging/audit.
  - `duration` integer: Run duration in seconds.

## Other responses

- `202`: Async extraction accepted — body carries {snapshot_id, status_url} (x_extract only).
- `400`: Bad request — missing resultsLimit or Idempotency-Key where required. Body is a Problem with `retryable:false` and a `hint`; never charged.
- `402`: Payment Required. Per-result reads require x402 upto on Base: authorize the maximum and pay only for delivered records, with a $0.0024 non-empty minimum and zero for empty results. Fixed-price operations may additionally offer exact x402 and MPP.
- `403`: Acting handle not connected to this wallet — connect it via /api/x-accounts/start first; never charged.
- `404`: Unknown tool path — GET /openapi.json for the valid list; never charged.
- `429`: Rate limited — `retryable:true`; retry unchanged after the Retry-After header; never charged.
- `500`: Unexpected handler error — inspect payment receipt before retrying.
- `502`: Upstream provider error — `retryable:true`; inspect payment receipt before retrying; prepaid operations may already be charged.
- `503`: Service capacity temporarily unavailable — `retryable:true`; retry later; never charged.

---

[API](https://skmtc.dev/twitr/apis/twitr-sh.md) · [All operations](https://skmtc.dev/twitr/apis/twitr-sh/llms.txt) · [OpenAPI document](https://skmtc.dev/twitr/apis/twitr-sh/revisions/f6390fcee344?raw)
