<!-- BusyBot node reference — https://busybot.net/tools/twitter/ -->

> Node: X (Twitter) (`twitter`) · Action (binary) · v1
> Category: Marketing · Credentials: X (Twitter) OAuth2 (`twitterOAuth2`)
> Updated: 2026-08-16

# X (Twitter)

> Create, like, retweet, search tweets, send DMs, and upload media on X (Twitter)

## Overview

The X (Twitter) tool provides full interaction with the Twitter/X platform via API v2. Supports four resources: (1) Tweet — create (with optional media upload via chunked 3-step upload to v1.1 endpoint), delete, like, retweet, and search recent tweets. (2) Direct Message — send a DM to a user (with optional media attachment). (3) User — look up users by username or ID, or get the authenticated user. (4) List — add a member to a list. Binary support: when creating a tweet with media, reads binary data from the input item, uploads via chunked media upload (INIT -> APPEND -> FINALIZE) to the v1.1 upload endpoint, then attaches the returned media_id to the tweet. Tweets use v2 endpoint, media upload uses v1.1 endpoint.

**Category:** Marketing  
**Tool Name:** `twitter`  
**Version:** 1

**Appearance:** Icon: `si-x` | Color: `#000000`

## Node Type

**Action (Binary)** — handles file/binary data operations

## Input / Output

| Direction | Port(s) |
|-----------|--------|
| Input | `Input` |
| Output | `Output`, `Error` |

## Credentials

This tool requires **X (Twitter) OAuth2** credentials.
See the [Credentials Guide](https://busybot.net/credentials/twitter-oauth2/) for setup instructions.

### Resources

| Resource | Value |
|----------|-------|
| Direct Message | `directMessage` |
| List | `list` |
| Tweet | `tweet` |
| User | `user` |

### Operations

Each resource has its own Operation list. Pick the resource first, then the operation.

| Resource | Operation | Value | Description |
|----------|-----------|-------|-------------|
| Tweet | Create | `create` | Create, quote, or reply to a tweet |
| Tweet | Delete | `delete` | Delete a tweet |
| Tweet | Like | `like` | Like a tweet |
| Tweet | Retweet | `retweet` | Retweet a tweet |
| Tweet | Search | `search` | Search for tweets from the last seven days |
| Direct Message | Create | `create` | Send a direct message to a user |
| List | Add Member | `add` | Add a member to a list |
| User | Get | `get` | Retrieve a user by username or ID |

### Parameters

Anywhere a tweet or list is identified you may paste either the bare numeric ID or the full URL — the node extracts the ID for you. Users are given as either the handle without the `@` or the numeric user ID.

#### Tweet: Create

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Text | `string` | Yes | — | The text of the tweet. URLs must be encoded. Links will be wrapped with t.co shortener and affect character count. |
| Upload Media | `boolean` | No | `false` | Whether to upload and attach binary media (image/video/GIF) from the input item to the tweet. |
| Binary Property (`binaryPropertyName`) | `string` | No | `data` | Name of the binary property on the input item containing the media to upload. Names are case-sensitive — see the upstream node's Binary Data panel for the exact names to use. _(shown when Upload Media is `true`)_ |
| Media Category | `options` | No | `auto` | The media category for the upload. Auto-detect uses the MIME type to determine category. _(shown when Upload Media is `true`)_ |
| | | | | Options: `auto` (determine media type from the MIME type), `tweet_image` (static image — JPEG, PNG, WebP), `tweet_gif` (animated GIF), `tweet_video` (video file — MP4) |
| Options (`additionalFields`) | `collection` | No | `{}` | Optional properties to set on the tweet. |
| — Location ID (`location`) | `string` | No | — | Geo place ID for location tagging. Note: location support is limited in Twitter API v2. |
| — Media ID (`mediaId`) | `string` | No | — | Pre-uploaded media ID to attach to the tweet. Use this instead of Upload Media if you already have a media_id. |
| — Quote Tweet ID (`quoteTweetId`) | `string` | No | — | Tweet ID or URL of the tweet to quote. |
| — Reply to Tweet ID (`replyToTweetId`) | `string` | No | — | Tweet ID or URL of the tweet to reply to. |

#### Tweet: Delete

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Tweet ID | `string` | Yes | — | The ID or URL of the tweet to delete. |

#### Tweet: Like

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Tweet ID | `string` | Yes | — | The ID or URL of the tweet to like. |

#### Tweet: Retweet

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Tweet ID | `string` | Yes | — | The ID or URL of the tweet to retweet. |

#### Tweet: Search

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Search Term (`searchText`) | `string` | Yes | — | A UTF-8, URL-encoded search query of 500 characters maximum, including operators. Queries may be limited by complexity. |
| Return All | `boolean` | No | `false` | Whether to return all results or only up to a given limit. |
| Limit | `number` | No | `50` | Max number of results to return. _(shown when Return All is `false`)_ |
| Search Options (`searchOptions`) | `collection` | No | `{}` | Optional search settings. |
| — Sort Order (`sortOrder`) | `options` | No | `recency` | The order in which to return results. |
| | | | | Options: `recency` (Recent), `relevancy` (Relevant) |
| — After (Start Time) (`startTime`) | `string` | No | — | Only return tweets after this time (ISO 8601 format). Must be within the last 7 days without Academic Research access. |
| — Before (End Time) (`endTime`) | `string` | No | — | Only return tweets before this time (ISO 8601 format). Must be within the last 7 days without Academic Research access. |
| — Tweet Fields (`tweetFields`) | `multiOptions` | No | `[]` | Additional tweet fields to include. Default fields: id, text, edit_history_tweet_ids. |
| | | | | Options: `attachments`, `author_id`, `context_annotations`, `conversation_id`, `created_at`, `edit_controls`, `entities`, `geo`, `id`, `in_reply_to_user_id`, `lang`, `non_public_metrics`, `public_metrics`, `organic_metrics`, `promoted_metrics`, `possibly_sensitive`, `referenced_tweets`, `reply_settings`, `source`, `text`, `withheld` |

#### Direct Message: Create

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| User | `string` | Yes | — | The recipient username (without @) or user ID. If a username is provided, it will be resolved to a user ID. |
| Text | `string` | Yes | — | The text of the direct message. Maximum 10,000 characters. |
| Additional Fields (`dmAdditionalFields`) | `collection` | No | `{}` | Optional properties to set on the direct message. |
| — Attachment Media ID (`attachmentMediaId`) | `string` | No | — | Pre-uploaded media ID to attach to the direct message. |

#### User: Get

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Me | `boolean` | No | `false` | Whether to return the authenticated user's profile instead of looking up a specific user. |
| User | `string` | Yes | — | The username (without @) or user ID to look up. _(shown when Me is `false`)_ |

#### List: Add Member

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| List (`listId`) | `string` | Yes | — | The list ID or URL to add the user to. |
| User | `string` | Yes | — | The username (without @) or user ID to add to the list. |

#### All Operations

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Twitter/X Account (`credentialId`) | `credential` | No | — | Connect your Twitter/X account via OAuth2. |
| Max Concurrency | `number` | No | `5` | Maximum number of items to process concurrently. Keep low due to Twitter rate limits. Accepts 1–50. |

## Output Data

The Twitter response is **merged onto the input item's JSON** at the top level — the returned object's fields sit alongside the fields the item already carried, so downstream nodes address them directly (`{{ $json.id }}`). A response field with the same name as an existing item field overwrites it. Binary data on the input item is forwarded unchanged onto every output item, including the media you just uploaded. The API's `data` envelope is unwrapped for you, so you address the record itself rather than `data.…`; a response that is not an object lands on the item as `result`.

**Only Search fans out.** Every other operation produces exactly one output item per input item.

| Operations | Output |
|------------|--------|
| Tweet Search | **One output item per tweet returned.** With Return All on, the node pages through the whole result set; with it off the list is trimmed to Limit. A search that matches nothing still emits **one** item, carrying `results: []`, so a no-match branch is never silently empty. |
| Tweet Create | One output item carrying the new tweet — `{{ $json.id }}` is the tweet ID. |
| Tweet Delete, Like and Retweet; Direct Message Create; User Get; List Add Member | One output item carrying the object the API returned for that action. |

Which fields come back from **Search** depends on **Tweet Fields**: without it each tweet carries only `id`, `text` and `edit_history_tweet_ids`, so add `author_id`, `created_at` or `public_metrics` when you need them downstream.

When both **Upload Media** and the **Media ID** option are set, the pre-uploaded Media ID wins and the freshly uploaded file is not attached. Use one or the other.

## Usage Examples

- Post a tweet with an image attachment
- Search for recent tweets about a topic
- Like a tweet by ID
- Retweet a tweet
- Send a direct message to a user
- Look up a user by username
- Add a user to a Twitter list
- Delete a tweet

## Example Configuration

Post a plain tweet:

```json
{
  "type": "twitter",
  "parameters": {
    "resource": "tweet",
    "operation": "create",
    "text": "Hello, Twitter! 🌟 #FirstTweet"
  }
}
```

Post a tweet with an image taken from an upstream node's binary output:

```json
{
  "type": "twitter",
  "parameters": {
    "resource": "tweet",
    "operation": "create",
    "text": "Check out this amazing photo! 📸",
    "uploadMedia": true,
    "binaryPropertyName": "image",
    "mediaCategory": "tweet_image"
  }
}
```

Reply to a tweet an upstream node found:

```json
{
  "type": "twitter",
  "parameters": {
    "resource": "tweet",
    "operation": "create",
    "text": "Great point! I totally agree with your perspective.",
    "additionalFields": {
      "replyToTweetId": "{{ $json.id }}"
    }
  }
}
```

Quote a tweet:

```json
{
  "type": "twitter",
  "parameters": {
    "resource": "tweet",
    "operation": "create",
    "text": "This is exactly what I was thinking about! Adding my perspective...",
    "additionalFields": {
      "quoteTweetId": "https://twitter.com/user/status/1187836157394112513"
    }
  }
}
```

Delete, like and retweet all take the same identifier:

```json
{
  "type": "twitter",
  "parameters": {
    "resource": "tweet",
    "operation": "like",
    "tweetId": "{{ $json.id }}"
  }
}
```

Search recent tweets and ask for richer fields:

```json
{
  "type": "twitter",
  "parameters": {
    "resource": "tweet",
    "operation": "search",
    "searchText": "#AI OR #MachineLearning",
    "returnAll": false,
    "limit": 50,
    "searchOptions": {
      "sortOrder": "recency",
      "tweetFields": ["author_id", "created_at", "public_metrics"]
    }
  }
}
```

Search a time window, paging through every match:

```json
{
  "type": "twitter",
  "parameters": {
    "resource": "tweet",
    "operation": "search",
    "searchText": "from:busybot",
    "returnAll": true,
    "searchOptions": {
      "startTime": "2026-08-01T00:00:00Z",
      "endTime": "2026-08-07T23:59:59Z",
      "sortOrder": "relevancy"
    }
  }
}
```

Send a direct message:

```json
{
  "type": "twitter",
  "parameters": {
    "resource": "directMessage",
    "operation": "create",
    "user": "{{ $json.username }}",
    "text": "Hey! Thanks for your interest in our project. Let's connect!"
  }
}
```

Send a direct message with a pre-uploaded attachment:

```json
{
  "type": "twitter",
  "parameters": {
    "resource": "directMessage",
    "operation": "create",
    "user": "1234567890",
    "text": "Here's the document you requested:",
    "dmAdditionalFields": {
      "attachmentMediaId": "1664279886239010824"
    }
  }
}
```

Read the authenticated account's own profile:

```json
{
  "type": "twitter",
  "parameters": {
    "resource": "user",
    "operation": "get",
    "me": true
  }
}
```

Look somebody else up by handle:

```json
{
  "type": "twitter",
  "parameters": {
    "resource": "user",
    "operation": "get",
    "me": false,
    "user": "{{ $json.handle }}"
  }
}
```

Add a user to a list:

```json
{
  "type": "twitter",
  "parameters": {
    "resource": "list",
    "operation": "add",
    "listId": "https://twitter.com/i/lists/99923132",
    "user": "{{ $json.handle }}"
  }
}
```

### Error Handling

| Mode | Behavior |
|------|----------|
| **stop** | Halts workflow on first error |
| **continue** | Skips failed items, passes successful ones through |
| **errorPort** | Routes failed items to Error output port |

## Tips

Interact with X (Twitter) — create/delete/like/retweet/search tweets, send DMs, manage lists, and upload media via chunked upload.

### Attaching Media

Point **Binary Property** at the property that actually holds the file. Binary property names are case-sensitive and come from the upstream node — check its Binary Data panel rather than assuming `data`. Leave **Media Category** on `auto` unless the file's MIME type is ambiguous; the upload is chunked, so large videos are handled the same way as small images.

### Search Workflow

1. Put your query in **Search Term**. Operators such as `from:`, `OR` and hashtags all work.
2. Use **Return All** for a complete sweep, or leave it off and set **Limit** for a predictable batch.
3. Narrow the window with **After** and **Before**. Search covers the last seven days unless your X plan grants a longer archive.
4. Add **Tweet Fields** for anything beyond the tweet's ID and text.

### Error Prevention

- Encode URLs inside tweet text — links are rewritten with the t.co shortener and count towards the character limit.
- Keep **Max Concurrency** low (5 or under) to stay inside X's rate limits.
- Prefer numeric user IDs over handles when you have them; handles are resolved with an extra lookup and change over time.
- Tweet and list fields accept a full URL, so you can pass a link straight through without stripping the ID yourself.
</content>