Repository: xdevplatform/Twitter-API-v2-sample-code
Branch: main
Commit: 99992dd773dd
Files: 236
Total size: 499.2 KB
Directory structure:
gitextract_8ed01k13/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── config.yml
│ └── workflows/
│ └── cla.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── api-index.json
├── java/
│ ├── README.md
│ ├── posts/
│ │ ├── FullArchiveSearchDemo.java
│ │ ├── FullArchiveTweetCountsDemo.java
│ │ ├── QuoteTweetsDemo.java
│ │ ├── RecentSearchDemo.java
│ │ ├── RecentTweetCountsDemo.java
│ │ ├── SearchRecent.java
│ │ └── TweetsDemo.java
│ ├── spaces/
│ │ ├── SearchSpacesDemo.java
│ │ └── SpacesLookupDemo.java
│ ├── streams/
│ │ ├── FilteredStreamDemo.java
│ │ └── SampledStream.java
│ ├── timelines/
│ │ ├── UserMentionsDemo.java
│ │ ├── UserTweetsDemo.java
│ │ └── reverse-chron-home-timeline-java-sdk.java
│ ├── usage/
│ │ └── UsageTweetsDemo.java
│ └── users/
│ ├── FollowersLookupDemo.java
│ ├── FollowingLookupDemo.java
│ ├── Lookup.java
│ └── UsersDemo.java
├── javascript/
│ ├── README.md
│ ├── compliance/
│ │ ├── create_jobs.js
│ │ ├── download_results.js
│ │ ├── get_jobs.js
│ │ ├── get_jobs_by_id.js
│ │ └── upload_ids.js
│ ├── lists/
│ │ ├── add_member.js
│ │ ├── create_list.js
│ │ ├── delete_list.js
│ │ ├── get_list_by_id.js
│ │ ├── get_list_followers.js
│ │ ├── get_list_members.js
│ │ ├── get_list_posts.js
│ │ ├── remove_member.js
│ │ └── update_list.js
│ ├── posts/
│ │ ├── create_post.js
│ │ ├── delete_post.js
│ │ ├── get_liking_users.js
│ │ ├── get_post_counts_all.js
│ │ ├── get_post_counts_recent.js
│ │ ├── get_posts_by_ids.js
│ │ ├── get_posts_by_ids_user_context.js
│ │ ├── get_quoted_posts.js
│ │ ├── get_reposted_by.js
│ │ ├── search_all.js
│ │ └── search_recent.js
│ ├── spaces/
│ │ ├── get_spaces_by_ids.js
│ │ └── search_spaces.js
│ ├── streams/
│ │ ├── stream_posts_filtered.js
│ │ └── stream_posts_sample.js
│ ├── usage/
│ │ └── get_usage.js
│ └── users/
│ ├── block/
│ │ └── get_blocking.js
│ ├── bookmark/
│ │ ├── create_bookmark.js
│ │ ├── delete_bookmark.js
│ │ └── get_bookmarks.js
│ ├── follow/
│ │ ├── get_followers.js
│ │ ├── get_followers_paginated.js
│ │ └── get_following_paginated.js
│ ├── get_users_by_usernames.js
│ ├── get_users_by_usernames_user_context.js
│ ├── get_users_me.js
│ ├── like/
│ │ ├── get_liked_posts.js
│ │ ├── like_post.js
│ │ └── unlike_post.js
│ ├── lists/
│ │ ├── follow_list.js
│ │ ├── get_followed_lists.js
│ │ ├── get_list_memberships.js
│ │ ├── get_owned_lists.js
│ │ ├── pin_list.js
│ │ ├── unfollow_list.js
│ │ └── unpin_list.js
│ ├── mute/
│ │ ├── get_muting.js
│ │ ├── mute_user.js
│ │ └── unmute_user.js
│ ├── repost/
│ │ ├── repost_post.js
│ │ └── unrepost_post.js
│ └── timeline/
│ ├── get_home_timeline.js
│ ├── get_mentions.js
│ ├── get_posts.js
│ └── get_posts_paginated.js
├── llms.txt
├── python/
│ ├── README.md
│ ├── activity/
│ │ ├── create_subscription.py
│ │ ├── delete_subscription.py
│ │ ├── list_subscriptions.py
│ │ ├── stream_events.py
│ │ └── update_subscription.py
│ ├── compliance/
│ │ ├── create_jobs.py
│ │ ├── download_results.py
│ │ ├── get_jobs.py
│ │ ├── get_jobs_by_id.py
│ │ └── upload_ids.py
│ ├── direct_messages/
│ │ ├── get_events_by_conversation.py
│ │ ├── get_one_to_one_conversation_events.py
│ │ ├── get_user_conversation_events.py
│ │ ├── post_dm_to_conversation.py
│ │ ├── post_group_conversation_dm.py
│ │ └── post_one_to_one_dm.py
│ ├── lists/
│ │ ├── add_member.py
│ │ ├── create_list.py
│ │ ├── delete_list.py
│ │ ├── get_list_by_id.py
│ │ ├── get_list_followers.py
│ │ ├── get_list_members.py
│ │ ├── get_list_posts.py
│ │ ├── remove_member.py
│ │ └── update_list.py
│ ├── media/
│ │ ├── media_upload_v2.py
│ │ └── upload.py
│ ├── posts/
│ │ ├── create_post.py
│ │ ├── delete_post.py
│ │ ├── get_liking_users.py
│ │ ├── get_post_by_id.py
│ │ ├── get_post_counts_all.py
│ │ ├── get_post_counts_recent.py
│ │ ├── get_posts_by_ids.py
│ │ ├── get_quoted_posts.py
│ │ ├── get_reposted_by.py
│ │ ├── hide_reply.py
│ │ ├── search_all.py
│ │ └── search_recent.py
│ ├── requirements.txt
│ ├── spaces/
│ │ ├── get_spaces_by_ids.py
│ │ └── search_spaces.py
│ ├── streams/
│ │ ├── stream_posts_filtered.py
│ │ └── stream_posts_sample.py
│ ├── usage/
│ │ └── get_usage.py
│ ├── users/
│ │ ├── block/
│ │ │ └── get_blocking.py
│ │ ├── bookmark/
│ │ │ ├── create_bookmark.py
│ │ │ ├── delete_bookmark.py
│ │ │ └── get_bookmarks.py
│ │ ├── follow/
│ │ │ ├── follow_user.py
│ │ │ ├── get_followers.py
│ │ │ ├── get_following.py
│ │ │ └── unfollow_user.py
│ │ ├── get_users_by_usernames.py
│ │ ├── get_users_by_usernames_user_context.py
│ │ ├── get_users_me.py
│ │ ├── like/
│ │ │ ├── get_liked_posts.py
│ │ │ ├── like_post.py
│ │ │ └── unlike_post.py
│ │ ├── lists/
│ │ │ ├── follow_list.py
│ │ │ ├── get_followed_lists.py
│ │ │ ├── get_list_memberships.py
│ │ │ ├── get_owned_lists.py
│ │ │ ├── get_pinned_lists.py
│ │ │ ├── pin_list.py
│ │ │ ├── unfollow_list.py
│ │ │ └── unpin_list.py
│ │ ├── mute/
│ │ │ ├── get_muting.py
│ │ │ ├── mute_user.py
│ │ │ └── unmute_user.py
│ │ ├── repost/
│ │ │ ├── get_reposts_of_me.py
│ │ │ ├── repost_post.py
│ │ │ └── unrepost_post.py
│ │ └── timeline/
│ │ ├── get_home_timeline.py
│ │ ├── get_mentions.py
│ │ └── get_posts.py
│ └── webhooks/
│ ├── delete_webhook.py
│ ├── list_webhooks.py
│ ├── register_webhook.py
│ ├── validate_webhook.py
│ └── webhook_server.py
├── r/
│ ├── posts/
│ │ ├── full-archive-search.r
│ │ ├── full_archive_tweet_counts.r
│ │ ├── recent-search.r
│ │ └── recent_tweet_counts.r
│ └── users/
│ └── get_users_with_bearer_token.r
└── ruby/
├── Gemfile
├── README.md
├── bookmarks/
│ └── bookmarks_lookup.rb
├── lists/
│ ├── List-Tweets.rb
│ ├── Pinned-List.rb
│ ├── add_member.rb
│ ├── create_a_list.rb
│ ├── delete_a_list.rb
│ ├── follow_list.rb
│ ├── list-followers-lookup.rb
│ ├── list-lookup-by-id.rb
│ ├── list-member-lookup.rb
│ ├── lookup.rb
│ ├── pin_list.rb
│ ├── remove_member.rb
│ ├── unfollow_list.rb
│ ├── unpin_list.rb
│ ├── update_a_list.rb
│ ├── user-list-followed.rb
│ ├── user-list-memberships.rb
│ └── user-owned-list-lookup.rb
├── posts/
│ ├── create_tweet.rb
│ ├── delete_tweet.rb
│ ├── full-archive-search.rb
│ ├── full_archive_tweet_counts.rb
│ ├── get_tweets_with_bearer_token.rb
│ ├── get_tweets_with_user_context.rb
│ ├── like_a_tweet.rb
│ ├── liked_tweets.rb
│ ├── liking_users.rb
│ ├── lookup.rb
│ ├── quote_tweets.rb
│ ├── recent_search.rb
│ ├── recent_tweet_counts.rb
│ ├── retweet_a_tweet.rb
│ ├── retweeted_by.rb
│ ├── search_recent.rb
│ ├── undo_a_retweet.rb
│ └── unlike_a_tweet.rb
├── spaces/
│ ├── search_spaces.rb
│ └── spaces_lookup.rb
├── streams/
│ ├── filtered_stream.rb
│ └── sampled_stream.rb
├── timelines/
│ ├── reverse-chron-home-timeline.rb
│ ├── user-mentions.rb
│ ├── user-tweets.rb
│ └── user_posts.rb
└── users/
├── block_a_user.rb
├── followers-lookup.rb
├── followers.rb
├── following-lookup.rb
├── get_users_me_with_user_context.rb
├── get_users_with_bearer_token.rb
├── get_users_with_user_context.rb
├── lookup.rb
├── lookup_blocks.rb
├── lookup_mutes.rb
├── mute_a_user.rb
├── unblock_a_user.rb
└── unmute_a_user.rb
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve this code
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
**Expected behavior**
A clear and concise description of what you expected to happen.
**Additional context**
Add any other context about the problem here.
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: Question about the API? Ask in the Twitter Developer Community
url: https://twittercommunity.com/c/twitter-api/twitter-api-v2/
about: For general API functionality questions, please ask in the developer forums.
================================================
FILE: .github/workflows/cla.yml
================================================
name: "CLA Assistant"
on:
issue_comment:
types: [created]
pull_request_target:
types: [opened,closed,synchronize]
jobs:
CLAssistant:
runs-on: ubuntu-latest
steps:
- name: "CLA Assistant"
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
# Alpha Release
uses: cla-assistant/github-action@v2.0.2-alpha
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PERSONAL_ACCESS_TOKEN : ${{ secrets.CLA_PAT }}
with:
remote-organization-name: twitter
remote-repository-name: .github-private
path-to-signatures: 'cla/signatures.json'
path-to-document: 'https://gist.github.com/twitter-service/a1ad5818c024dc4265f8b60e6d043f26'
custom-allsigned-prcomment: 'All Contributors have signed the CLA. If the commit check is not passing, a maintainer must go the Checks tab of this PR and rerun the GitHub Action.'
branch: 'main'
================================================
FILE: .gitignore
================================================
*.gem
*.rbc
/.config
/coverage/
/InstalledFiles
/pkg/
/spec/reports/
/spec/examples.txt
/test/tmp/
/test/version_tmp/
/tmp/
.DS_Store
node_modules/
package-lock.json
package.json
yarn.lock
../node_modules/
../package.json
../yarn.lock
# Used by dotenv library to load environment variables.
# .env
# Ignore Byebug command history file.
.byebug_history
## Specific to RubyMotion:
.dat*
.repl_history
build/
*.bridgesupport
build-iPhoneOS/
build-iPhoneSimulator/
## Specific to RubyMotion (use of CocoaPods):
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# vendor/Pods/
## Documentation cache and generated files:
/.yardoc/
/_yardoc/
/doc/
/rdoc/
## Environment normalization:
/.bundle/
/vendor/bundle
/lib/bundler/man/
# for a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# Gemfile.lock
# .ruby-version
# .ruby-gemset
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
# .rubocop-https?--*
================================================
FILE: CODE_OF_CONDUCT.md
================================================
We feel that a welcoming community is important and we ask that you follow Twitter's
[Open Source Code of Conduct](https://github.com/twitter/code-of-conduct/blob/master/code-of-conduct.md)
in all interactions with the community.
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2020 @TwitterDev
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
# X API v2 Sample Code
[](https://developer.x.com/en/docs/twitter-api)
Working code samples for the **X API v2** in Python, JavaScript, Ruby, Java, and R.
## 📁 Repository Structure
```
├── python/ # 65 Python examples
├── javascript/ # 59 JavaScript examples
├── ruby/ # 58 Ruby examples
├── java/ # 19 Java examples
├── r/ # 5 R examples
├── llms.txt # LLM-friendly documentation
└── api-index.json # Machine-readable endpoint catalog
```
## 🚀 Quick Start
### 1. Get API Credentials
Sign up at the [X Developer Portal](https://developer.x.com/en/portal/dashboard).
### 2. Set Environment Variables
**For read-only operations (search, lookup):**
```bash
export BEARER_TOKEN='your_bearer_token'
```
**For user actions (post, like, repost, bookmark, etc.):**
```bash
export CLIENT_ID='your_client_id'
export CLIENT_SECRET='your_client_secret'
```
**For OAuth 1.0a (legacy endpoints):**
```bash
export CONSUMER_KEY='your_consumer_key'
export CONSUMER_SECRET='your_consumer_secret'
```
### 3. Run an Example
```bash
# Python
cd python && pip install -r requirements.txt
python posts/search_recent.py
# JavaScript
cd javascript
node posts/search_recent.js
# Ruby
cd ruby && bundle install
ruby posts/search_recent.rb
# Java
cd java
javac -cp ".:lib/*" posts/RecentSearchDemo.java
java -cp ".:lib/*" RecentSearchDemo
```
## 📚 Examples by Category
| Category | Python | JavaScript | Ruby | Java | R |
|----------|--------|------------|------|------|---|
| Posts (search, create, delete, likes, reposts) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Users (lookup, followers, following, blocks, mutes) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Timelines (user, mentions, home) | ✅ | ✅ | ✅ | ✅ | |
| Streams (filtered, sampled) | ✅ | ✅ | ✅ | ✅ | |
| Lists (lookup, manage, members, follow) | ✅ | ✅ | ✅ | | |
| Spaces (lookup, search) | ✅ | ✅ | ✅ | ✅ | |
| Bookmarks | ✅ | ✅ | ✅ | | |
| Direct Messages | ✅ | | | | |
| Media Upload | ✅ | | | | |
| Compliance | ✅ | ✅ | | | |
| Usage | ✅ | ✅ | | ✅ | |
## 🔐 Authentication
| Type | Use Case | Env Vars |
|------|----------|----------|
| Bearer Token | Read-only (search, lookup) | `BEARER_TOKEN` |
| OAuth 2.0 PKCE | User actions (post, like, repost, bookmark, mute, etc.) | `CLIENT_ID`, `CLIENT_SECRET` |
| OAuth 1.0a | Legacy endpoints (if applicable) | `CONSUMER_KEY`, `CONSUMER_SECRET` |
## 🤖 For LLMs
- **`llms.txt`** - Context file for AI assistants
- **`api-index.json`** - Machine-readable endpoint catalog
## 🔗 Resources
- [X API Documentation](https://developer.x.com/en/docs/twitter-api)
- [Developer Portal](https://developer.x.com/en/portal/dashboard)
## 📄 License
Apache 2.0
================================================
FILE: api-index.json
================================================
{
"name": "X API v2 Sample Code",
"version": "2.0",
"base_url": "https://api.x.com/2",
"languages": ["python", "javascript", "ruby", "java"],
"endpoints": [
{
"name": "Create Post",
"path": "/tweets",
"method": "POST",
"auth": ["oauth1", "oauth2-user"],
"folder": "posts",
"files": {
"python": "create_post.py",
"javascript": "create_post.js"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets"
},
{
"name": "Delete Post",
"path": "/tweets/:id",
"method": "DELETE",
"auth": ["oauth1", "oauth2-user"],
"folder": "posts",
"files": {
"python": "delete_post.py",
"javascript": "delete_post.js"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/delete-tweets-id"
},
{
"name": "Post Lookup",
"path": "/tweets",
"method": "GET",
"auth": ["bearer", "oauth1", "oauth2-user"],
"folder": "posts",
"files": {
"python": "lookup.py",
"javascript": "lookup.js",
"ruby": "lookup.rb"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets"
},
{
"name": "Recent Search",
"path": "/tweets/search/recent",
"method": "GET",
"auth": ["bearer", "oauth2-user"],
"folder": "posts",
"files": {
"python": "search_recent.py",
"javascript": "search_recent.js",
"ruby": "search_recent.rb",
"java": "SearchRecent.java"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent"
},
{
"name": "Full Archive Search",
"path": "/tweets/search/all",
"method": "GET",
"auth": ["bearer"],
"folder": "posts",
"files": {
"python": "search_full_archive.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-all",
"note": "Requires Academic Research access"
},
{
"name": "Recent Post Counts",
"path": "/tweets/counts/recent",
"method": "GET",
"auth": ["bearer"],
"folder": "posts",
"files": {
"python": "counts_recent.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-recent"
},
{
"name": "Quote Posts",
"path": "/tweets/:id/quote_tweets",
"method": "GET",
"auth": ["bearer", "oauth2-user"],
"folder": "posts",
"files": {
"python": "quote_posts.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/quote-tweets/api-reference/get-tweets-id-quote_tweets"
},
{
"name": "Repost",
"path": "/users/:id/retweets",
"method": "POST",
"auth": ["oauth1", "oauth2-user"],
"folder": "posts",
"files": {
"python": "repost.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/retweets/api-reference/post-users-id-retweets"
},
{
"name": "Undo Repost",
"path": "/users/:id/retweets/:source_tweet_id",
"method": "DELETE",
"auth": ["oauth1", "oauth2-user"],
"folder": "posts",
"files": {
"python": "undo_repost.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/retweets/api-reference/delete-users-id-retweets-tweet_id"
},
{
"name": "Reposted By",
"path": "/tweets/:id/retweeted_by",
"method": "GET",
"auth": ["bearer", "oauth2-user"],
"folder": "posts",
"files": {
"python": "reposted_by.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/retweets/api-reference/get-tweets-id-retweeted_by"
},
{
"name": "Like Post",
"path": "/users/:id/likes",
"method": "POST",
"auth": ["oauth1", "oauth2-user"],
"folder": "posts",
"files": {
"python": "like.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/post-users-id-likes"
},
{
"name": "Unlike Post",
"path": "/users/:id/likes/:tweet_id",
"method": "DELETE",
"auth": ["oauth1", "oauth2-user"],
"folder": "posts",
"files": {
"python": "unlike.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/delete-users-id-likes-tweet_id"
},
{
"name": "Liking Users",
"path": "/tweets/:id/liking_users",
"method": "GET",
"auth": ["bearer", "oauth2-user"],
"folder": "posts",
"files": {
"python": "liking_users.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/get-tweets-id-liking_users"
},
{
"name": "Liked Posts",
"path": "/users/:id/liked_tweets",
"method": "GET",
"auth": ["bearer", "oauth2-user"],
"folder": "posts",
"files": {
"python": "liked_posts.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/get-users-id-liked_tweets"
},
{
"name": "User Lookup",
"path": "/users/by",
"method": "GET",
"auth": ["bearer", "oauth1", "oauth2-user"],
"folder": "users",
"files": {
"python": "lookup.py",
"javascript": "lookup.js",
"ruby": "lookup.rb",
"java": "Lookup.java"
},
"docs": "https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by"
},
{
"name": "Authenticated User (Me)",
"path": "/users/me",
"method": "GET",
"auth": ["oauth1", "oauth2-user"],
"folder": "users",
"files": {
"python": "me.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me"
},
{
"name": "User Followers",
"path": "/users/:id/followers",
"method": "GET",
"auth": ["bearer", "oauth2-user"],
"folder": "users",
"files": {
"python": "followers.py",
"javascript": "followers.js",
"ruby": "followers.rb"
},
"docs": "https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers"
},
{
"name": "User Following",
"path": "/users/:id/following",
"method": "GET",
"auth": ["bearer", "oauth2-user"],
"folder": "users",
"files": {
"python": "following.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following"
},
{
"name": "Block User",
"path": "/users/:id/blocking",
"method": "POST",
"auth": ["oauth1", "oauth2-user"],
"folder": "users",
"files": {
"python": "block.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/users/blocks/api-reference/post-users-user_id-blocking"
},
{
"name": "Unblock User",
"path": "/users/:source_user_id/blocking/:target_user_id",
"method": "DELETE",
"auth": ["oauth1", "oauth2-user"],
"folder": "users",
"files": {
"python": "unblock.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/users/blocks/api-reference/delete-users-user_id-blocking"
},
{
"name": "Blocked Users",
"path": "/users/:id/blocking",
"method": "GET",
"auth": ["oauth1", "oauth2-user"],
"folder": "users",
"files": {
"python": "blocked.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/users/blocks/api-reference/get-users-blocking"
},
{
"name": "Mute User",
"path": "/users/:id/muting",
"method": "POST",
"auth": ["oauth1", "oauth2-user"],
"folder": "users",
"files": {
"python": "mute.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/users/mutes/api-reference/post-users-user_id-muting"
},
{
"name": "Unmute User",
"path": "/users/:source_user_id/muting/:target_user_id",
"method": "DELETE",
"auth": ["oauth1", "oauth2-user"],
"folder": "users",
"files": {
"python": "unmute.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/users/mutes/api-reference/delete-users-user_id-muting"
},
{
"name": "Muted Users",
"path": "/users/:id/muting",
"method": "GET",
"auth": ["oauth1", "oauth2-user"],
"folder": "users",
"files": {
"python": "muted.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/users/mutes/api-reference/get-users-muting"
},
{
"name": "User Posts Timeline",
"path": "/users/:id/tweets",
"method": "GET",
"auth": ["bearer", "oauth2-user"],
"folder": "timelines",
"files": {
"python": "user_posts.py",
"javascript": "user_posts.js",
"ruby": "user_posts.rb"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets"
},
{
"name": "User Mentions Timeline",
"path": "/users/:id/mentions",
"method": "GET",
"auth": ["bearer", "oauth2-user"],
"folder": "timelines",
"files": {
"python": "user_mentions.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-mentions"
},
{
"name": "Home Timeline",
"path": "/users/:id/reverse_chronological_timeline",
"method": "GET",
"auth": ["oauth1", "oauth2-user"],
"folder": "timelines",
"files": {
"python": "home_timeline.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-reverse-chronological-timeline"
},
{
"name": "Filtered Stream",
"path": "/tweets/search/stream",
"method": "GET",
"auth": ["bearer"],
"folder": "streams",
"files": {
"python": "filtered_stream.py",
"javascript": "filtered_stream.js"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream"
},
{
"name": "Sampled Stream",
"path": "/tweets/sample/stream",
"method": "GET",
"auth": ["bearer"],
"folder": "streams",
"files": {
"python": "sampled_stream.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/volume-streams/api-reference/get-tweets-sample-stream"
},
{
"name": "Bookmarks Lookup",
"path": "/users/:id/bookmarks",
"method": "GET",
"auth": ["oauth2-user"],
"folder": "bookmarks",
"files": {
"python": "lookup.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/bookmarks/api-reference/get-users-id-bookmarks"
},
{
"name": "Create Bookmark",
"path": "/users/:id/bookmarks",
"method": "POST",
"auth": ["oauth2-user"],
"folder": "bookmarks",
"files": {
"python": "create.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/bookmarks/api-reference/post-users-id-bookmarks"
},
{
"name": "Delete Bookmark",
"path": "/users/:id/bookmarks/:tweet_id",
"method": "DELETE",
"auth": ["oauth2-user"],
"folder": "bookmarks",
"files": {
"python": "delete.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/tweets/bookmarks/api-reference/delete-users-id-bookmarks-tweet_id"
},
{
"name": "Spaces Lookup",
"path": "/spaces",
"method": "GET",
"auth": ["bearer", "oauth2-user"],
"folder": "spaces",
"files": {
"python": "lookup.py",
"javascript": "lookup.js"
},
"docs": "https://developer.x.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces"
},
{
"name": "Spaces Search",
"path": "/spaces/search",
"method": "GET",
"auth": ["bearer", "oauth2-user"],
"folder": "spaces",
"files": {
"python": "search.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/spaces/search/api-reference/get-spaces-search"
},
{
"name": "List Lookup",
"path": "/lists/:id",
"method": "GET",
"auth": ["bearer", "oauth2-user"],
"folder": "lists",
"files": {
"python": "lookup.py",
"javascript": "lookup.js",
"ruby": "lookup.rb"
},
"docs": "https://developer.x.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id"
},
{
"name": "Create List",
"path": "/lists",
"method": "POST",
"auth": ["oauth1", "oauth2-user"],
"folder": "lists",
"files": {
"python": "create.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-lists"
},
{
"name": "Delete List",
"path": "/lists/:id",
"method": "DELETE",
"auth": ["oauth1", "oauth2-user"],
"folder": "lists",
"files": {
"python": "delete.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id"
},
{
"name": "DM Events Lookup",
"path": "/dm_events",
"method": "GET",
"auth": ["oauth1", "oauth2-user"],
"folder": "direct_messages",
"files": {
"python": "lookup.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/direct-messages/lookup/api-reference/get-dm-events"
},
{
"name": "Send DM",
"path": "/dm_conversations/with/:participant_id/messages",
"method": "POST",
"auth": ["oauth1", "oauth2-user"],
"folder": "direct_messages",
"files": {
"python": "send.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/direct-messages/manage/api-reference/post-dm-conversations-with-participant_id-messages"
},
{
"name": "Create Compliance Job",
"path": "/compliance/jobs",
"method": "POST",
"auth": ["bearer"],
"folder": "compliance",
"files": {
"python": "create_job.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs"
},
{
"name": "Get Compliance Jobs",
"path": "/compliance/jobs",
"method": "GET",
"auth": ["bearer"],
"folder": "compliance",
"files": {
"python": "get_jobs.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs"
},
{
"name": "API Usage",
"path": "/usage/tweets",
"method": "GET",
"auth": ["bearer"],
"folder": "usage",
"files": {
"python": "get_usage.py"
},
"docs": "https://developer.x.com/en/docs/twitter-api/usage/api-reference/get-usage-tweets"
}
]
}
================================================
FILE: java/README.md
================================================
# X API v2 - Java Examples
Working Java code samples for the X (formerly Twitter) API v2.
## Setup
### 1. Install Java 11+
```bash
java --version
```
### 2. Add dependencies
Using Maven, add to your `pom.xml`:
```xml
org.apache.httpcomponents
httpclient
4.5.13
com.google.code.gson
gson
2.9.1
```
### 3. Set environment variables
**For read-only operations (search, lookup):**
```bash
export BEARER_TOKEN='your_bearer_token'
```
**For user actions (post, like, repost, bookmark, etc.):**
```bash
export CLIENT_ID='your_client_id'
export CLIENT_SECRET='your_client_secret'
```
**Note:** Most user action examples require OAuth 2.0 authentication with `CLIENT_ID` and `CLIENT_SECRET`. Read-only examples (search, lookup) only require `BEARER_TOKEN`.
## Examples by Category
### Posts
- `posts/FullArchiveSearchDemo.java` - Full archive search demo
- `posts/FullArchiveTweetCountsDemo.java` - Full archive tweet counts demo
- `posts/QuoteTweetsDemo.java` - Get posts that quote a post
- `posts/RecentSearchDemo.java` - Recent search demo (last 7 days)
- `posts/RecentTweetCountsDemo.java` - Recent tweet counts demo
- `posts/SearchRecent.java` - Recent search (last 7 days)
- `posts/TweetsDemo.java` - Look up posts by ID
### Users
- `users/FollowersLookupDemo.java` - Get user's followers
- `users/FollowingLookupDemo.java` - Get users a user is following
- `users/Lookup.java` - Look up users by username
- `users/UsersDemo.java` - Users lookup demo
### Timelines
- `timelines/reverse-chron-home-timeline-java-sdk.java` - Get home timeline (reverse chronological)
- `timelines/UserMentionsDemo.java` - Get user mentions timeline
- `timelines/UserTweetsDemo.java` - Get user's posts timeline
### Streams
- `streams/FilteredStreamDemo.java` - Filtered stream with rules
- `streams/SampledStream.java` - Sampled stream
### Spaces
- `spaces/SearchSpacesDemo.java` - Search for Spaces
- `spaces/SpacesLookupDemo.java` - Look up Spaces by ID
### Usage
- `usage/UsageTweetsDemo.java` - Get API usage information
## Building and Running
### Compile
```bash
# Compile a single file
javac -cp ".:lib/*" posts/SearchRecent.java
# Or compile all files
find . -name "*.java" -exec javac -cp ".:lib/*" {} \;
```
### Run
```bash
# Run a single example
java -cp ".:lib/*" posts.SearchRecent
# Or with package structure
java -cp ".:lib/*" posts/RecentSearchDemo
```
## More Information
- [X API Documentation](https://developer.x.com/en/docs/twitter-api)
- [X Developer Portal](https://developer.x.com/en/portal/dashboard)
================================================
FILE: java/posts/FullArchiveSearchDemo.java
================================================
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/*
* Sample code to demonstrate the use of the Full archive search endpoint
* */
public class FullArchiveSearchDemo {
// To set your enviornment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
//Replace the search term with a term of your choice
String response = search("from:TwitterDev OR from:SnowBotDev OR from:DailyNASA", bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the full-archive search endpoint with a the search term passed to it as a query parameter
* */
private static String search(String searchString, String bearerToken) throws IOException, URISyntaxException {
String searchResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/tweets/search/all");
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("query", searchString));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
searchResponse = EntityUtils.toString(entity, "UTF-8");
}
return searchResponse;
}
}
================================================
FILE: java/posts/FullArchiveTweetCountsDemo.java
================================================
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/*
* Sample code to demonstrate the use of the Full-archive Tweet counts endpoint
* */
public class FullArchiveTweetCountsDemo {
// To set your enviornment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
//Replace the search term with a term of your choice
String response = getTweetCounts("from:TwitterDev", bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the full-archive Tweet counts endpoint with a the search term passed to it as a query parameter
* */
private static String getTweetCounts(String searchString, String bearerToken) throws IOException, URISyntaxException {
String searchResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/tweets/counts/all");
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("query", searchString));
queryParameters.add(new BasicNameValuePair("granularity", "day"));
queryParameters.add(new BasicNameValuePair("start_time", "2021-01-01T00:00:00Z"));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
searchResponse = EntityUtils.toString(entity, "UTF-8");
}
return searchResponse;
}
}
================================================
FILE: java/posts/QuoteTweetsDemo.java
================================================
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
/*
* Sample code to demonstrate the use of the v2 Quote Tweets endpoint
* */
public class QuoteTweetsDemo {
// To set your environment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
final String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
//Replace with Tweet ID below
String response = getTweets(20, bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the v2 Quote Tweets endpoint by Tweet ID
* */
private static String getTweets(int tweetId, String bearerToken) throws IOException, URISyntaxException {
String tweetResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder(String.format("https://api.x.com/2/tweets/%s/quote_tweets", tweetId));
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("tweet.fields", "created_at"));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
tweetResponse = EntityUtils.toString(entity, "UTF-8");
}
return tweetResponse;
}
}
================================================
FILE: java/posts/RecentSearchDemo.java
================================================
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/*
* Sample code to demonstrate the use of the Recent search endpoint
* */
public class RecentSearchDemo {
// To set your enviornment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
//Replace the search term with a term of your choice
String response = search("from:TwitterDev OR from:SnowBotDev OR from:DailyNASA", bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting you bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the recent search endpoint with a the search term passed to it as a query parameter
* */
private static String search(String searchString, String bearerToken) throws IOException, URISyntaxException {
String searchResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/tweets/search/recent");
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("query", searchString));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
searchResponse = EntityUtils.toString(entity, "UTF-8");
}
return searchResponse;
}
}
================================================
FILE: java/posts/RecentTweetCountsDemo.java
================================================
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/*
* Sample code to demonstrate the use of the Recent Tweet counts endpoint
* */
public class RecentTweetCountsDemo {
// To set your enviornment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
//Replace the search term with a term of your choice
String response = getTweetCounts("from:TwitterDev", bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting you bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the recent Tweet counts endpoint with a the search term passed to it as a query parameter
* */
private static String getTweetCounts(String searchString, String bearerToken) throws IOException, URISyntaxException {
String searchResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/tweets/counts/recent");
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("query", searchString));
queryParameters.add(new BasicNameValuePair("granularity", "day"));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
searchResponse = EntityUtils.toString(entity, "UTF-8");
}
return searchResponse;
}
}
================================================
FILE: java/posts/SearchRecent.java
================================================
/**
* Recent Search - X API v2
*
* Endpoint: GET https://api.x.com/2/tweets/search/recent
* Docs: https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent
*
* Authentication: Bearer Token (App-only)
* Required env vars: BEARER_TOKEN
*
* Dependencies: org.apache.httpcomponents:httpclient, com.google.code.gson:gson
*/
import java.io.IOException;
import java.net.URISyntaxException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class SearchRecent {
public static void main(String[] args) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (bearerToken == null) {
System.err.println("BEARER_TOKEN environment variable not set");
System.exit(1);
}
String response = search("from:XDevelopers -is:retweet", bearerToken);
System.out.println(response);
}
private static String search(String query, String bearerToken) throws IOException, URISyntaxException {
String searchUrl = "https://api.x.com/2/tweets/search/recent";
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder(searchUrl);
uriBuilder.addParameter("query", query);
uriBuilder.addParameter("tweet.fields", "author_id,created_at");
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", "Bearer " + bearerToken);
httpGet.setHeader("User-Agent", "v2RecentSearchJava");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (entity != null) {
return EntityUtils.toString(entity, "UTF-8");
} else {
return "No response";
}
}
}
================================================
FILE: java/posts/TweetsDemo.java
================================================
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
/*
* Sample code to demonstrate the use of the v2 Tweets endpoint
* */
public class TweetsDemo {
// To set your enviornment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
//Replace comma separated ids with Tweets Ids of your choice
String response = getTweets("1138505981460193280,1261326399320715264", bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting you bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the v2 Tweets endpoint with ids as query parameter
* */
private static String getTweets(String ids, String bearerToken) throws IOException, URISyntaxException {
String tweetResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/tweets");
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("ids", ids));
queryParameters.add(new BasicNameValuePair("tweet.fields", "created_at"));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
tweetResponse = EntityUtils.toString(entity, "UTF-8");
}
return tweetResponse;
}
}
================================================
FILE: java/spaces/SearchSpacesDemo.java
================================================
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/*
* Sample code to demonstrate the use of the Spaces lookup endpoint
* */
public class SpacesLookupDemo {
// To set your enviornment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
//Replace SPACE_ID with the ID of a Space
String response = getSpaceById("SPACE_ID", bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the Spaces lookup endpoint with the ID passed to it as a query parameter
* */
private static String getSpaceById(String spaceId, String bearerToken) throws IOException, URISyntaxException {
String searchResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/spaces");
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("ids", spaceId));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("User-Agent", "v2SpacesLookupJava");
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
searchResponse = EntityUtils.toString(entity, "UTF-8");
}
return searchResponse;
}
}
================================================
FILE: java/spaces/SpacesLookupDemo.java
================================================
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/*
* Sample code to demonstrate the use of the Spaces lookup endpoint
* */
public class SpacesLookupDemo {
// To set your enviornment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
//Replace SPACE_ID with the ID of a Space
String response = getSpaceById("SPACE_ID", bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the Spaces lookup endpoint with the ID passed to it as a query parameter
* */
private static String getSpaceById(String spaceId, String bearerToken) throws IOException, URISyntaxException {
String searchResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/spaces");
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("ids", spaceId));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("User-Agent", "v2SpacesLookupJava");
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
searchResponse = EntityUtils.toString(entity, "UTF-8");
}
return searchResponse;
}
}
================================================
FILE: java/streams/FilteredStreamDemo.java
================================================
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.*;
import java.net.URISyntaxException;
import java.util.*;
/*
* Sample code to demonstrate the use of the Filtered Stream endpoint
* */
public class FilteredStreamDemo {
// To set your enviornment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
Map rules = new HashMap<>();
rules.put("cats has:images", "cat images");
rules.put("dogs has:images", "dog images");
setupRules(bearerToken, rules);
connectStream(bearerToken);
} else {
System.out.println("There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the filtered stream endpoint and streams Tweets from it
* */
private static void connectStream(String bearerToken) throws IOException, URISyntaxException {
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/tweets/search/stream");
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
BufferedReader reader = new BufferedReader(new InputStreamReader((entity.getContent())));
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}
}
}
/*
* Helper method to setup rules before streaming data
* */
private static void setupRules(String bearerToken, Map rules) throws IOException, URISyntaxException {
List existingRules = getRules(bearerToken);
if (existingRules.size() > 0) {
deleteRules(bearerToken, existingRules);
}
createRules(bearerToken, rules);
}
/*
* Helper method to create rules for filtering
* */
private static void createRules(String bearerToken, Map rules) throws URISyntaxException, IOException {
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/tweets/search/stream/rules");
HttpPost httpPost = new HttpPost(uriBuilder.build());
httpPost.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpPost.setHeader("content-type", "application/json");
StringEntity body = new StringEntity(getFormattedString("{\"add\": [%s]}", rules));
httpPost.setEntity(body);
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
if (null != entity) {
System.out.println(EntityUtils.toString(entity, "UTF-8"));
}
}
/*
* Helper method to get existing rules
* */
private static List getRules(String bearerToken) throws URISyntaxException, IOException {
List rules = new ArrayList<>();
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/tweets/search/stream/rules");
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("content-type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
JSONObject json = new JSONObject(EntityUtils.toString(entity, "UTF-8"));
if (json.length() > 1) {
JSONArray array = (JSONArray) json.get("data");
for (int i = 0; i < array.length(); i++) {
JSONObject jsonObject = (JSONObject) array.get(i);
rules.add(jsonObject.getString("id"));
}
}
}
return rules;
}
/*
* Helper method to delete rules
* */
private static void deleteRules(String bearerToken, List existingRules) throws URISyntaxException, IOException {
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/tweets/search/stream/rules");
HttpPost httpPost = new HttpPost(uriBuilder.build());
httpPost.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpPost.setHeader("content-type", "application/json");
StringEntity body = new StringEntity(getFormattedString("{ \"delete\": { \"ids\": [%s]}}", existingRules));
httpPost.setEntity(body);
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
if (null != entity) {
System.out.println(EntityUtils.toString(entity, "UTF-8"));
}
}
private static String getFormattedString(String string, List ids) {
StringBuilder sb = new StringBuilder();
if (ids.size() == 1) {
return String.format(string, "\"" + ids.get(0) + "\"");
} else {
for (String id : ids) {
sb.append("\"" + id + "\"" + ",");
}
String result = sb.toString();
return String.format(string, result.substring(0, result.length() - 1));
}
}
private static String getFormattedString(String string, Map rules) {
StringBuilder sb = new StringBuilder();
if (rules.size() == 1) {
String key = rules.keySet().iterator().next();
return String.format(string, "{\"value\": \"" + key + "\", \"tag\": \"" + rules.get(key) + "\"}");
} else {
for (Map.Entry entry : rules.entrySet()) {
String value = entry.getKey();
String tag = entry.getValue();
sb.append("{\"value\": \"" + value + "\", \"tag\": \"" + tag + "\"}" + ",");
}
String result = sb.toString();
return String.format(string, result.substring(0, result.length() - 1));
}
}
}
================================================
FILE: java/streams/SampledStream.java
================================================
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
/*
* Sample code to demonstrate the use of the Sampled Stream endpoint
* */
public class SampledStreamDemo {
// To set your enviornment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
connectStream(bearerToken);
} else {
System.out.println("There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the sample stream endpoint and streams Tweets from it
* */
private static void connectStream(String bearerToken) throws IOException, URISyntaxException {
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/tweets/sample/stream");
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
BufferedReader reader = new BufferedReader(new InputStreamReader((entity.getContent())));
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}
}
}
}
================================================
FILE: java/timelines/UserMentionsDemo.java
================================================
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
/*
* Sample code to demonstrate the use of the v2 User Mentions timeline endpoint
* */
public class UserMentionsDemo {
// To set your environment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
final String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
//Replace with user ID below
String response = getTweets("2244994945", bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the v2 User Mentions timeline endpoint by user ID
* */
private static String getTweets(String userId, String bearerToken) throws IOException, URISyntaxException {
String tweetResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder(String.format("https://api.x.com/2/users/%s/mentions", userId));
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("tweet.fields", "created_at"));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
tweetResponse = EntityUtils.toString(entity, "UTF-8");
}
return tweetResponse;
}
}
================================================
FILE: java/timelines/UserTweetsDemo.java
================================================
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
/*
* Sample code to demonstrate the use of the v2 User Tweet timeline endpoint
* */
public class UserTweetsDemo {
// To set your environment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
final String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
// Replace with user ID below
String response = getTweets("2244994945", bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the v2 User Tweet timeline endpoint by user ID
* */
private static String getTweets(String userId, String bearerToken) throws IOException, URISyntaxException {
String tweetResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder(String.format("https://api.x.com/2/users/%s/tweets", userId));
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("tweet.fields", "created_at"));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
tweetResponse = EntityUtils.toString(entity, "UTF-8");
}
return tweetResponse;
}
}
================================================
FILE: java/timelines/reverse-chron-home-timeline-java-sdk.java
================================================
package com.twitter.clientlib.auth;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import com.github.scribejava.core.model.OAuth2AccessToken;
import com.github.scribejava.core.pkce.PKCE;
import com.github.scribejava.core.pkce.PKCECodeChallengeMethod;
import com.twitter.clientlib.TwitterCredentialsBearer;
import com.twitter.clientlib.ApiClient;
import com.twitter.clientlib.ApiException;
import com.twitter.clientlib.Configuration;
import com.twitter.clientlib.auth.*;
import com.twitter.clientlib.model.*;
import com.twitter.clientlib.TwitterCredentialsOAuth2;
import com.twitter.clientlib.api.TwitterApi;
import com.twitter.clientlib.api.BookmarksApi;
import java.util.List;
import java.util.Set;
import java.util.Arrays;
import java.util.HashSet;
import java.time.OffsetDateTime;
import org.json.*;
/**
* This is an example of getting an OAuth2 access token and using it to call an API.
* It's expected to set TWITTER_OAUTH2_CLIENT_ID & TWITTER_OAUTH2_CLIENT_SECRET in TwitterCredentialsOAuth2
*
* Example steps:
* 1. Getting the App Authorization URL.
* 2. User should click the URL and authorize it.
* 3. After receiving the access token, setting the values into TwitterCredentialsOAuth2.
* 4. Call the API.
*/
public class OAuth20GetAccessToken {
public static void main(String[] args) {
OAuth20GetAccessToken example = new OAuth20GetAccessToken();
TwitterCredentialsOAuth2 credentials = new TwitterCredentialsOAuth2("REPLACE-WITH-CLIENT-ID",
"REPLACE-WITH-CLIENT-SECRET",
null,
null);
OAuth2AccessToken accessToken = example.getAccessToken(credentials);
if (accessToken == null) {
return;
}
// Setting the access & refresh tokens into TwitterCredentialsOAuth2
credentials.setTwitterOauth2AccessToken(accessToken.getAccessToken());
credentials.setTwitterOauth2RefreshToken(accessToken.getRefreshToken());
example.callApi(credentials);
}
public OAuth2AccessToken getAccessToken(TwitterCredentialsOAuth2 credentials) {
TwitterOAuth20Service service = new TwitterOAuth20Service(
credentials.getTwitterOauth2ClientId(),
credentials.getTwitterOAuth2ClientSecret(),
"https://www.example.com/oauth",
"offline.access tweet.read users.read");
OAuth2AccessToken accessToken = null;
try {
final Scanner in = new Scanner(System.in, "UTF-8");
System.out.println("Fetching the Authorization URL...");
final String secretState = "state";
PKCE pkce = new PKCE();
pkce.setCodeChallenge("challenge");
pkce.setCodeChallengeMethod(PKCECodeChallengeMethod.PLAIN);
pkce.setCodeVerifier("challenge");
String authorizationUrl = service.getAuthorizationUrl(pkce, secretState);
System.out.println("Go to the Authorization URL and authorize your App:\n" +
authorizationUrl + "\nAfter that paste the authorization code here\n>>");
final String code = in.nextLine();
System.out.println("\nTrading the Authorization Code for an Access Token...");
accessToken = service.getAccessToken(pkce, code);
System.out.println("Access token: " + accessToken.getAccessToken());
System.out.println("Refresh token: " + accessToken.getRefreshToken());
} catch (Exception e) {
System.err.println("Error while getting the access token:\n " + e);
e.printStackTrace();
}
return accessToken;
}
public void callApi(TwitterCredentialsOAuth2 credentials) {
TwitterApi apiInstance = new TwitterApi();
apiInstance.setTwitterCredentials(credentials);
// Set the params values
String sinceId = "791775337160081409"; // String | The minimum Tweet ID to be included in the result set. This parameter takes precedence over start_time if both are specified.
String untilId = "1346889436626259968"; // String | The maximum Tweet ID to be included in the result set. This parameter takes precedence over end_time if both are specified.
Integer maxResults = 56; // Integer | The maximum number of results
String paginationToken = "paginationToken_example"; // String | This parameter is used to get the next 'page' of results.
OffsetDateTime startTime = OffsetDateTime.parse("2021-02-01T18:40:40.000Z"); // OffsetDateTime | YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp from which the Tweets will be provided. The since_id parameter takes precedence if it is also specified.
OffsetDateTime endTime = OffsetDateTime.parse("2021-02-14T18:40:40.000Z"); // OffsetDateTime | YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Tweets will be provided. The until_id parameter takes precedence if it is also specified.
Set expansions = new HashSet<>(Arrays.asList()); // Set | A comma separated list of fields to expand.
Set tweetFields = new HashSet<>(Arrays.asList()); // Set | A comma separated list of Tweet fields to display.
Set userFields = new HashSet<>(Arrays.asList()); // Set | A comma separated list of User fields to display.
Set mediaFields = new HashSet<>(Arrays.asList()); // Set | A comma separated list of Media fields to display.
Set placeFields = new HashSet<>(Arrays.asList()); // Set | A comma separated list of Place fields to display.
Set pollFields = new HashSet<>(Arrays.asList()); // Set | A comma separated list of Poll fields to display.
try {
//Gets the authorized user ID and parses it into an JSON object
SingleUserLookupResponse userData = apiInstance.users().findMyUser(null, null, null);
String jsonString = userData.getData().toJson();
JSONObject obj = new JSONObject(jsonString);
String userId = obj.getString("id");
//Passes the parsed ID into the userIdTimeline request
GenericTweetsTimelineResponse result = apiInstance.tweets().usersIdTimeline(userId, sinceId, untilId, maxResults, null, paginationToken, startTime, endTime, expansions, tweetFields, userFields, mediaFields, placeFields, pollFields);
System.out.println(result);
} catch (ApiException e) {
System.err.println("Exception when calling UsersApi#usersIdTimeline");
System.err.println("Status code: " + e.getCode());
System.err.println("Reason: " + e.getResponseBody());
System.err.println("Response headers: " + e.getResponseHeaders());
e.printStackTrace();
}
}
}
================================================
FILE: java/usage/UsageTweetsDemo.java
================================================
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
/*
* Sample code to demonstrate the use of the v2 Usage Tweets endpoint
* */
public class UsageTweetsDemo {
// To set your enviornment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
String response = getUsageTweets(bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting you bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the v2 Usage Tweets endpoint
* */
private static String getUsageTweets(String bearerToken) throws IOException, URISyntaxException {
String usageTweetsResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/usage/tweets");
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
usageTweetsResponse = EntityUtils.toString(entity, "UTF-8");
}
return usageTweetsResponse;
}
}
================================================
FILE: java/users/FollowersLookupDemo.java
================================================
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
/*
* Sample code to demonstrate the use of the v2 followers lookup endpoint
* */
public class FollowersLookupDemo {
// To set your environment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
final String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
// Replace with user ID below
String response = getFollowers("2244994945", bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the v2 followers lookup endpoint by user ID
* */
private static String getFollowers(String userId, String bearerToken) throws IOException, URISyntaxException {
String tweetResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder(String.format("https://api.x.com/2/users/%s/followers", userId));
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("user.fields", "created_at"));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
tweetResponse = EntityUtils.toString(entity, "UTF-8");
}
return tweetResponse;
}
}
================================================
FILE: java/users/FollowingLookupDemo.java
================================================
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
/*
* Sample code to demonstrate the use of the v2 following lookup endpoint
* */
public class FollowingLookupDemo {
// To set your environment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
final String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
// Replace with user ID below
String response = getFollowing("2244994945", bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting your bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the v2 following lookup endpoint
* */
private static String getFollowing(String userId, String bearerToken) throws IOException, URISyntaxException {
String tweetResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder(String.format("https://api.x.com/2/users/%s/following", userId));
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("user.fields", "created_at"));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
tweetResponse = EntityUtils.toString(entity, "UTF-8");
}
return tweetResponse;
}
}
================================================
FILE: java/users/Lookup.java
================================================
/**
* User Lookup - X API v2
*
* Endpoint: GET https://api.x.com/2/users/by
* Docs: https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by
*
* Authentication: Bearer Token (App-only)
* Required env vars: BEARER_TOKEN
*
* Dependencies: org.apache.httpcomponents:httpclient, com.google.code.gson:gson
*/
import java.io.IOException;
import java.net.URISyntaxException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class Lookup {
public static void main(String[] args) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (bearerToken == null) {
System.err.println("BEARER_TOKEN environment variable not set");
System.exit(1);
}
String response = lookupUsers("XDevelopers,X", bearerToken);
System.out.println(response);
}
private static String lookupUsers(String usernames, String bearerToken) throws IOException, URISyntaxException {
String userLookupUrl = "https://api.x.com/2/users/by";
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder(userLookupUrl);
uriBuilder.addParameter("usernames", usernames);
uriBuilder.addParameter("user.fields", "created_at,description,public_metrics");
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", "Bearer " + bearerToken);
httpGet.setHeader("User-Agent", "v2UserLookupJava");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (entity != null) {
return EntityUtils.toString(entity, "UTF-8");
} else {
return "No response";
}
}
}
================================================
FILE: java/users/UsersDemo.java
================================================
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
/*
* Sample code to demonstrate the use of the v2 Users endpoint
* */
public class UsersDemo {
// To set your enviornment variables in your terminal run the following line:
// export 'BEARER_TOKEN'=''
public static void main(String args[]) throws IOException, URISyntaxException {
String bearerToken = System.getenv("BEARER_TOKEN");
if (null != bearerToken) {
//Replace comma separated usernames with usernames of your choice
String response = getUsers("TwitterDev,TwitterEng", bearerToken);
System.out.println(response);
} else {
System.out.println("There was a problem getting you bearer token. Please make sure you set the BEARER_TOKEN environment variable");
}
}
/*
* This method calls the v2 Users endpoint with usernames as query parameter
* */
private static String getUsers(String usernames, String bearerToken) throws IOException, URISyntaxException {
String userResponse = null;
HttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD).build())
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.x.com/2/users/by");
ArrayList queryParameters;
queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("usernames", usernames));
queryParameters.add(new BasicNameValuePair("user.fields", "created_at,description,pinned_tweet_id"));
uriBuilder.addParameters(queryParameters);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setHeader("Authorization", String.format("Bearer %s", bearerToken));
httpGet.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (null != entity) {
userResponse = EntityUtils.toString(entity, "UTF-8");
}
return userResponse;
}
}
================================================
FILE: javascript/README.md
================================================
# X API v2 - JavaScript (Node.js) Examples
Working JavaScript code samples for the X (formerly Twitter) API v2.
## Setup
### 1. Install Node.js 14+
```bash
node --version
```
### 2. Install dependencies
No package.json is required. Examples use Node.js built-in modules or standard libraries.
### 3. Set environment variables
**For read-only operations (search, lookup):**
```bash
export BEARER_TOKEN='your_bearer_token'
```
**For user actions (post, like, repost, bookmark, mute, etc.):**
```bash
export CLIENT_ID='your_client_id'
export CLIENT_SECRET='your_client_secret'
```
**Note:** Most user action examples (create post, like, repost, bookmark, mute, block, etc.) require OAuth 2.0 authentication with `CLIENT_ID` and `CLIENT_SECRET`. Read-only examples (search, lookup) only require `BEARER_TOKEN`.
## Examples by Category
### Posts
- `posts/create_post.js` - Create a new post (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `posts/delete_post.js` - Delete a post (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `posts/get_liking_users.js` - Get users who liked a post (requires `CLIENT_ID`, `CLIENT_SECRET` for user context)
- `posts/get_post_counts_all.js` - Get post counts (full archive)
- `posts/get_post_counts_recent.js` - Get post counts (recent)
- `posts/get_posts_by_ids.js` - Look up posts by ID (bearer token)
- `posts/get_posts_by_ids_user_context.js` - Look up posts by ID (user context) (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `posts/get_quoted_posts.js` - Get posts that quote a post
- `posts/get_reposted_by.js` - Get users who reposted a post
- `posts/search_all.js` - Full archive search
- `posts/search_recent.js` - Recent search (last 7 days)
### Users
- `users/get_users_by_usernames.js` - Look up users by username (bearer token)
- `users/get_users_by_usernames_user_context.js` - Look up users by username (user context) (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/get_users_me.js` - Get authenticated user (me) (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Block
- `users/block/get_blocking.js` - Get users blocked by a user (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Bookmark
- `users/bookmark/create_bookmark.js` - Create a bookmark (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/bookmark/delete_bookmark.js` - Delete a bookmark (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/bookmark/get_bookmarks.js` - Get user's bookmarks (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Follow
- `users/follow/get_followers.js` - Get user's followers
- `users/follow/get_followers_paginated.js` - Get user's followers (paginated)
- `users/follow/get_following_paginated.js` - Get users a user is following (paginated)
#### User Actions - Like
- `users/like/get_liked_posts.js` - Get posts liked by a user (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/like/like_post.js` - Like a post (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/like/unlike_post.js` - Unlike a post (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Lists
- `users/lists/follow_list.js` - Follow a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/lists/get_followed_lists.js` - Get lists followed by a user
- `users/lists/get_list_memberships.js` - Get list memberships
- `users/lists/get_owned_lists.js` - Get lists owned by a user
- `users/lists/pin_list.js` - Pin a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/lists/unfollow_list.js` - Unfollow a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/lists/unpin_list.js` - Unpin a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Mute
- `users/mute/get_muting.js` - Get users muted by a user (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/mute/mute_user.js` - Mute a user (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/mute/unmute_user.js` - Unmute a user (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Repost
- `users/repost/repost_post.js` - Repost a post (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/repost/unrepost_post.js` - Undo a repost (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Timeline
- `users/timeline/get_home_timeline.js` - Get home timeline (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/timeline/get_mentions.js` - Get user mentions timeline
- `users/timeline/get_posts.js` - Get user's posts timeline
- `users/timeline/get_posts_paginated.js` - Get user's posts timeline (paginated)
### Timelines
- See `users/timeline/` directory for timeline examples
### Streams
- `streams/stream_posts_filtered.js` - Filtered stream with rules
- `streams/stream_posts_sample.js` - Sampled stream
### Lists
- `lists/add_member.js` - Add member to a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `lists/create_list.js` - Create a new list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `lists/delete_list.js` - Delete a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `lists/get_list_by_id.js` - Get list by ID
- `lists/get_list_followers.js` - Get list followers
- `lists/get_list_members.js` - Get list members
- `lists/get_list_posts.js` - Get posts from a list
- `lists/remove_member.js` - Remove member from a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `lists/update_list.js` - Update a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
### Spaces
- `spaces/get_spaces_by_ids.js` - Look up Spaces by ID
- `spaces/search_spaces.js` - Search for Spaces
### Compliance
- `compliance/create_jobs.js` - Create compliance job
- `compliance/download_results.js` - Download compliance results
- `compliance/get_jobs_by_id.js` - Get compliance job by ID
- `compliance/get_jobs.js` - Get compliance jobs
- `compliance/upload_ids.js` - Upload IDs for compliance
### Usage
- `usage/get_usage.js` - Get API usage information
## Running Examples
```bash
# Make sure environment variables are set
node posts/search_recent.js
```
## More Information
- [X API Documentation](https://developer.x.com/en/docs/twitter-api)
- [X Developer Portal](https://developer.x.com/en/portal/dashboard)
================================================
FILE: javascript/compliance/create_jobs.js
================================================
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
// For User Compliance Job, replace type value with users instead of tweets
// Also replace the name value with your desired job name
const data = {
type: "tweets",
name: 'my_batch_compliance_job'
};
(async () => {
try {
// Make request
const response = await client.compliance.createJobs(data);
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/compliance/download_results.js
================================================
// Replace with your job download_url
downloadUrl = ''
async function getRequest() {
const res = await fetch(downloadUrl, {
headers: {
'Accept-Encoding': 'gzip, deflate, br'
}
})
if (res.ok) {
return await res.text();
} else {
throw new Error('Unsuccessful request');
}
}
(async () => {
try {
// Make request
const response = await getRequest();
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/compliance/get_jobs.js
================================================
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
// For User Compliance job, replace the value for type with users
const params = {
type: "tweets"
};
(async () => {
try {
// Make request
const response = await client.compliance.getJobs(params);
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/compliance/get_jobs_by_id.js
================================================
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
// Replace with your job ID
const jobId = '';
(async () => {
try {
// Make request
const response = await client.compliance.getJobsById(jobId);
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/compliance/upload_ids.js
================================================
const fs = require('fs');
// Replace with your job download_url
const uploadUrl = '';
// Replace with your file path that contains the list of Post IDs or User IDs, one ID per line
const filePath = '/path/to/file';
async function getRequest() {
const readStream = fs.createReadStream(filePath);
const fileBuffer = await new Promise((resolve, reject) => {
const chunks = [];
readStream.on('data', chunk => chunks.push(chunk));
readStream.on('end', () => resolve(Buffer.concat(chunks)));
readStream.on('error', reject);
});
const res = await fetch(uploadUrl, {
method: 'PUT',
body: fileBuffer,
headers: {
"Content-Type": "text/plain"
}
});
if (res.ok) {
return res.status;
} else {
throw new Error('Unsuccessful request');
}
}
(async () => {
try {
// Make request
const response = await getRequest();
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/lists/add_member.js
================================================
// Add member to a list using OAuth 2.0 to authorize the user
// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-list-id with your own list ID or one of an authenticated user
const listId = "your-list-id";
// Be sure to replace user-id-to-add with the user id you wish to add.
// You can find a user ID by using the user lookup endpoint
const userId = "user-id-to-add";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.lists.addMember(listId, { body: { user_id: userId } });
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/lists/create_list.js
================================================
// Create a new list using OAuth 2.0 to authorize the user
// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to add replace name-of-list with the name you wish to call the list.
// description and private keys are optional
const data = {
name: "name-of-list",
description: "description-of-list",
private: false,
};
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.lists.create({ body: data });
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/lists/delete_list.js
================================================
// Delete an existing list the authenticated user owns - using OAuth 2.0 to authorize the user
// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to add replace the your-list-id with the id of the list you wish to delete.
const targetListId = "your-list-id";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.lists.delete(targetListId);
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/lists/get_list_by_id.js
================================================
/**
* List Lookup - X API v2
*
* Endpoint: GET https://api.x.com/2/lists/:id
* Docs: https://developer.x.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id
*
* Authentication: Bearer Token (App-only) or OAuth (User Context)
* Required env vars: BEARER_TOKEN
*/
const { Client } = require('@xdevplatform/xdk');
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
// Replace with the list ID you want to look up
const listId = "84839422";
(async () => {
try {
const response = await client.lists.getById(listId, {
listFields: ['created_at', 'follower_count', 'member_count', 'owner_id', 'description']
});
console.dir(response, { depth: null });
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/lists/get_list_followers.js
================================================
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
const id = "list-id";
(async () => {
try {
// These are the parameters for the API request
// by default, only the User ID and name are returned
const response = await client.lists.getFollowers(id, {
userFields: ['pinned_tweet_id', 'created_at'], // Edit optional query parameters here
expansions: ['pinned_tweet_id'], // expansions is used to include the Post object
tweetFields: ['created_at'] // Edit optional query parameters here
});
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/lists/get_list_members.js
================================================
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
const id = "list-id";
(async () => {
try {
// These are the parameters for the API request
// by default, only the User ID and name are returned
const response = await client.lists.getMembers(id, {
userFields: ['pinned_tweet_id', 'created_at'], // Edit optional query parameters here
expansions: ['pinned_tweet_id'], // expansions is used to include the Post object
tweetFields: ['created_at'] // Edit optional query parameters here
});
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/lists/get_list_posts.js
================================================
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
const id = "list-id";
(async () => {
try {
// These are the parameters for the API request
// by default, only the Post ID and text are returned
const response = await client.lists.getPosts(id, {
tweetFields: ['lang', 'author_id'], // Edit optional query parameters here
expansions: ['author_id'], // expansions is used to include the user object
userFields: ['created_at'] // Edit optional query parameters here
});
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/lists/remove_member.js
================================================
// Remove member from a list using OAuth 2.0 to authorize the user
// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-list-id with your own list ID or one of an authenticated user
const listId = "your-list-id";
// Be sure to replace user-id-to-remove with the user id you wish to remove.
// You can find a user ID by using the user lookup endpoint
const userId = "user-id-to-remove";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.lists.removeMemberByUserId(listId, userId);
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/lists/update_list.js
================================================
// Update the metadata of an existing list the authenticated user owns - using OAuth 2.0 to authorize the user
// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to add replace update-name-of-list with the name you wish to call the list.
// name, description and private are all optional
const data = {
name: "update-name-of-list",
description: "update-description-of-list",
private: false,
};
// Be sure to add replace the your-list-id with the list id of the list you wish to update.
const targetListId = "your-list-id";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.lists.update(targetListId, { body: data });
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/posts/create_post.js
================================================
/**
* Create Post - X API v2
*
* Endpoint: POST https://api.x.com/2/posts
* Docs: https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets
*
* Authentication: OAuth 2.0 (User Context)
* Required env vars: CLIENT_ID, CLIENT_SECRET
*/
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// The text content of the post. You can also add parameters for polls,
// quote posts, reply settings, and more.
const data = {
text: "Hello world!"
};
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log('Please go here and authorize:', authUrl);
// Input callback URL from terminal
const redirectCallback = await input('Paste the redirected callback URL here: ');
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.posts.create(data);
console.dir(response, { depth: null });
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/posts/delete_post.js
================================================
/**
* Delete Post - X API v2
*
* Endpoint: DELETE https://api.x.com/2/posts/:id
* Docs: https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/delete-tweets-id
*
* Authentication: OAuth 2.0 (User Context)
* Required env vars: CLIENT_ID, CLIENT_SECRET
*/
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Replace with the post ID you want to delete
const postId = "post-id-to-delete";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'tweet.write','offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log('Please go here and authorize:', authUrl);
// Input callback URL from terminal
const redirectCallback = await input('Paste the redirected callback URL here: ');
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.posts.delete(postId);
console.dir(response, { depth: null });
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/posts/get_liking_users.js
================================================
// Get liking users for a post using OAuth 2.0 to authorize the user
// https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-tweets-id-liking_users
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// You can replace the ID given with the Post ID you wish to get liking users for.
// You can find an ID by using the Post lookup endpoint
const id = "1354143047324299264";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'like.read', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// These are the parameters for the API request
// by default, only the Post ID and text are returned
const response = await client.posts.getLikingUsers(id, {
tweetFields: ['lang', 'author_id'], // Edit optional query parameters here
userFields: ['created_at'] // Edit optional query parameters here
});
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/posts/get_post_counts_all.js
================================================
// Search for public posts across the whole Twitter archive
// https://developer.twitter.com/en/docs/twitter-api/tweets/search/quick-start/full-archive-search
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
(async () => {
try {
// Edit query parameters below and specify a search query
// optional params: start_time,end_time,since_id,until_id,next_token,granularity
const response = await client.posts.getCountsAll('from:xdevelopers', {
granularity: 'day',
startTime: '2021-01-01T00:00:00Z'
});
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/posts/get_post_counts_recent.js
================================================
// Search for posts within the past seven days
// https://developer.twitter.com/en/docs/twitter-api/tweets/search/quick-start/recent-search
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
(async () => {
try {
// Edit query parameters below and specify a search query
// optional params: start_time,end_time,since_id,until_id,next_token,granularity
const response = await client.posts.getCountsRecent('from:xdevelopers', {
granularity: 'day'
});
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/posts/get_posts_by_ids.js
================================================
/**
* Post Lookup - X API v2
*
* Endpoint: GET https://api.x.com/2/posts
* Docs: https://developer.x.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets
*
* Authentication: Bearer Token (App-only) or OAuth (User Context)
* Required env vars: BEARER_TOKEN
*/
const { Client } = require('@xdevplatform/xdk');
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
// These are the parameters for the API request
// specify Post IDs to fetch, and any additional fields that are required
// by default, only the Post ID and text are returned
const postIDs = ['1278747501642657792', '1275828087666679809']; // Edit the Post IDs to look up
(async () => {
try {
// Post IDs to look up (comma-separated, up to 100)
const response = await client.posts.getByIds(postIDs, {
tweetFields: ['created_at', 'author_id', 'lang', 'source', 'public_metrics'],
userFields: ['created_at'],
expansions: ['author_id']
});
console.dir(response, { depth: null });
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/posts/get_posts_by_ids_user_context.js
================================================
// Get Post objects by ID, using user authentication
// https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// These are the parameters for the API request
// specify Post IDs to fetch, and any additional fields that are required
// by default, only the Post ID and text are returned
const postIDs = ['1278747501642657792', '1275828087666679809']; // Edit the Post IDs to look up
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log('Please go here and authorize:', authUrl);
// Input callback URL from terminal
const redirectCallback = await input('Paste the redirected callback URL here: ');
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.posts.getByIds(postIDs, {
tweetFields: ['lang', 'author_id'],
userFields: ['created_at']
});
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/posts/get_quoted_posts.js
================================================
// Get Quote Posts by Post ID
// https://developer.twitter.com/en/docs/twitter-api/tweets/quote-tweets-lookup/quick-start
const { Client, PostPaginator } = require('@xdevplatform/xdk');
const postId = '1980412193624785337';
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const bearerToken = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: bearerToken });
const getQuotePosts = async () => {
console.log("Retrieving quote posts...");
// Use paginator for automatic pagination
const quotePosts = new PostPaginator(
async (token) => {
const res = await client.posts.getQuoted(postId, {
maxResults: 100,
paginationToken: token,
tweetFields: ['created_at']
});
return {
data: res.data ?? [],
meta: res.meta,
includes: res.includes,
errors: res.errors
};
}
);
// Fetch all pages
await quotePosts.fetchNext();
while (!quotePosts.done) {
await quotePosts.fetchNext();
}
console.dir(quotePosts.posts, {
depth: null
});
console.log(`Got ${quotePosts.posts.length} quote posts for Post ID ${postId}!`);
}
getQuotePosts().catch(err => {
console.error('Error:', err);
process.exit(-1);
});
================================================
FILE: javascript/posts/get_reposted_by.js
================================================
// Get Reposted By (Users who reposted) by Post ID
// https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/get-tweets-id-retweeted_by
const { Client, UserPaginator } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const bearerToken = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: bearerToken });
// You can replace the ID given with the Post ID you wish to lookup reposting users for
// You can find an ID by using the Post lookup endpoint
const postId = "1980412193624785337";
const getRepostedBy = async () => {
console.log("Retrieving users who reposted...");
// Use paginator for automatic pagination
const repostedBy = new UserPaginator(
async (token) => {
const res = await client.posts.getRepostedBy(postId, {
maxResults: 100,
paginationToken: token,
tweetFields: ['lang', 'author_id'],
userFields: ['created_at']
});
return {
data: res.data ?? [],
meta: res.meta,
includes: res.includes,
errors: res.errors
};
}
);
// Fetch all pages
await repostedBy.fetchNext();
while (!repostedBy.done) {
await repostedBy.fetchNext();
}
console.dir(repostedBy.users, {
depth: null
});
console.log(`Got ${repostedBy.users.length} users who reposted Post ID ${postId}!`);
}
getRepostedBy().catch(err => {
console.error('Error:', err);
process.exit(-1);
});
================================================
FILE: javascript/posts/search_all.js
================================================
// Search for public posts across the whole Twitter archive
// https://developer.twitter.com/en/docs/twitter-api/tweets/search/quick-start/full-archive-search
const { Client, PostPaginator } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const bearerToken = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: bearerToken });
const query = 'from:xdevelopers';
const searchAll = async () => {
console.log("Searching full archive...");
// Use paginator for automatic pagination
const searchResults = new PostPaginator(
async (token) => {
const res = await client.posts.searchAll(query, {
maxResults: 100,
nextToken: token,
tweetFields: ['author_id']
});
return {
data: res.data ?? [],
meta: res.meta,
includes: res.includes,
errors: res.errors
};
}
);
// Fetch all pages
await searchResults.fetchNext();
while (!searchResults.done) {
await searchResults.fetchNext();
}
console.dir(searchResults.posts, {
depth: null
});
console.log(`Got ${searchResults.posts.length} posts for query: ${query}`);
}
searchAll().catch(err => {
console.error('Error:', err);
process.exit(-1);
});
================================================
FILE: javascript/posts/search_recent.js
================================================
/**
* Recent Search - X API v2
*
* Endpoint: GET https://api.x.com/2/posts/search/recent
* Docs: https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent
*
* Authentication: Bearer Token (App-only)
* Required env vars: BEARER_TOKEN
*
* Note: Returns posts from the last 7 days.
* This example demonstrates automatic pagination using PostPaginator
* to fetch all pages of results.
*/
const { Client, PostPaginator } = require('@xdevplatform/xdk');
const bearerToken = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: bearerToken });
const query = 'from:x -is:retweet';
const searchRecent = async () => {
console.log("Searching recent posts...");
// Use paginator for automatic pagination
const searchResults = new PostPaginator(
async (token) => {
const res = await client.posts.searchRecent(query, {
maxResults: 100,
nextToken: token,
tweetFields: ['author_id', 'created_at']
});
return {
data: res.data ?? [],
meta: res.meta,
includes: res.includes,
errors: res.errors
};
}
);
// Fetch all pages
await searchResults.fetchNext();
while (!searchResults.done) {
await searchResults.fetchNext();
}
console.dir(searchResults.posts, {
depth: null
});
console.log(`Got ${searchResults.posts.length} posts for query: ${query}`);
}
searchRecent().catch(err => {
console.error('Error:', err);
process.exit(-1);
});
================================================
FILE: javascript/spaces/get_spaces_by_ids.js
================================================
/**
* Spaces Lookup - X API v2
*
* Endpoint: GET https://api.x.com/2/spaces
* Docs: https://developer.x.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces
*
* Authentication: Bearer Token (App-only) or OAuth (User Context)
* Required env vars: BEARER_TOKEN
*/
const { Client } = require('@xdevplatform/xdk');
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
const spaceIds = ['1DXxyRYNejbKM'];
(async () => {
try {
// Replace with Space IDs you want to look up
const response = await client.spaces.getByIds(spaceIds, {
spaceFields: ['host_ids', 'created_at', 'creator_id', 'participant_count', 'title', 'state']
});
console.dir(response, { depth: null });
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/spaces/search_spaces.js
================================================
// Lookup Spaces by ID
// https://developer.twitter.com/en/docs/twitter-api/spaces/lookup
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
const query = 'NBA';
(async () => {
try {
// Edit query parameters below and specify a search query
// optional params: host_ids,conversation_controls,created_at,creator_id,id,invited_user_ids,is_ticketed,lang,media_key,participants,scheduled_start,speaker_ids,started_at,state,title,updated_at
const response = await client.spaces.search(query, {
spaceFields: ['title', 'created_at'],
expansions: ['creator_id']
});
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/streams/stream_posts_filtered.js
================================================
// Open a realtime stream of posts, filtered according to rules
// https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/quick-start
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
// this sets up two rules - the value is the search terms to match on, and the tag is an identifier that
// will be applied to the posts returned to show which rule they matched
// with a standard project with Basic Access, you can add up to 25 concurrent rules to your stream, and
// each rule can be up to 512 characters long
// Edit rules as desired below
const rules = [{
value: 'dog has:images -is:retweet',
tag: 'dog pictures'
},
{
value: 'cat has:images -grumpy',
tag: 'cat pictures'
},
];
(async () => {
try {
// Gets the complete list of rules currently applied to the stream
const currentRules = await client.stream.getRules();
// Delete all rules. Comment the line below if you want to keep your existing rules.
if (currentRules.data && currentRules.data.length > 0) {
const ids = currentRules.data.map(rule => rule.id);
await client.stream.updateRules({ delete: { ids: ids } });
}
// Add rules to the stream. Comment the line below if you don't want to add new rules.
await client.stream.updateRules({ add: rules });
// Listen to the stream
const stream = await client.stream.posts({
tweetFields: ['id', 'text', 'created_at']
});
stream.on('data', (event) => {
// event is the parsed JSON line (data/includes/matching_rules)
console.log('New data:', event);
});
stream.on('error', (e) => {
console.error('Stream error:', e);
if (e.detail === "This stream is currently at the maximum allowed connection limit.") {
console.log(e.detail);
process.exit(1);
}
});
stream.on('keepAlive', () => {
// heartbeat event - keep alive signal received
});
stream.on('close', () => {
console.log('Stream closed');
});
} catch (e) {
console.error(e);
process.exit(1);
}
})();
================================================
FILE: javascript/streams/stream_posts_sample.js
================================================
// Open a live stream of roughly 1% random sample of publicly available posts
// https://developer.twitter.com/en/docs/twitter-api/tweets/volume-streams/quick-start
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
(async () => {
try {
// 1% sampled public posts
const stream = await client.stream.postsSample({
tweetFields: ['id', 'text', 'created_at']
});
// Listen to events
stream.on('data', (event) => {
// event is the parsed JSON line (data/includes/matching_rules)
console.log('New data:', event);
});
stream.on('error', (e) => {
console.error('Stream error:', e);
if (e.status === 401) {
console.log('Unauthorized');
process.exit(1);
} else if (e.detail === "This stream is currently at the maximum allowed connection limit.") {
console.log(e.detail);
process.exit(1);
}
});
stream.on('keepAlive', () => {
// heartbeat event - keep alive signal received
});
stream.on('close', () => {
console.log('Stream closed');
});
} catch (e) {
console.error('Error:', e);
process.exit(1);
}
})();
================================================
FILE: javascript/usage/get_usage.js
================================================
// Get Posts Usage
// https://developer.twitter.com/en/docs/twitter-api/usage/tweets
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
(async () => {
try {
// Make request
const response = await client.usage.get();
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/block/get_blocking.js
================================================
// Block a user, using user authentication
// https://developer.twitter.com/en/docs/twitter-api/users/blocks/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticated user
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access', 'block.read']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log('Please go here and authorize:', authUrl);
// Input callback URL from terminal
const redirectCallback = await input('Paste the redirected callback URL here: ');
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.getBlocking(userId);
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/bookmark/create_bookmark.js
================================================
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
//Helper function to parse callback
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
//Helper terminal input function
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const CLIENT_ID = process.env.CLIENT_ID;
const CLIENT_SECRET = process.env.CLIENT_SECRET;
// Include the ID of the Post you wish to bookmark
const tweetId = "post-id"; // Replace with the ID of the Post you wish to bookmark
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'bookmark.write']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const STATE = "my-state";
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(STATE);
console.log(`Please go here and authorize:`, authUrl);
//Input users callback url in terminal
const redirectCallback = await input("Paste the redirected callback here: ");
//Parse callback
const { state, code } = getQueryStringParams(redirectCallback);
if (state !== STATE) {
console.log("State isn't matching");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
//Get the user ID
const meResponse = await client.users.getMe();
const userId = meResponse.data?.id;
if (!userId) {
throw new Error('Could not get user ID');
}
//Makes api call
const postBookmark = await client.users.createBookmark(userId, { tweet_id: tweetId });
console.dir(postBookmark, {
depth: null,
});
process.exit();
} catch (error) {
console.log(error);
process.exit(-1);
}
})();
================================================
FILE: javascript/users/bookmark/delete_bookmark.js
================================================
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
//Helper function to parse callback
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
//Helper terminal input function
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const CLIENT_ID = process.env.CLIENT_ID;
const CLIENT_SECRET = process.env.CLIENT_SECRET;
// Include the ID of the Post you wish to unbookmark
const tweetId = "1996314591996129694";
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'bookmark.write']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const STATE = "my-state";
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(STATE);
console.log(`Please go here and authorize:`, authUrl);
//Input users callback url in terminal
const redirectCallback = await input("Paste the redirected callback here: ");
//Parse callback
const { state, code } = getQueryStringParams(redirectCallback);
if (state !== STATE) {
console.log("State isn't matching");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
//Get the user ID
const meResponse = await client.users.getMe();
const userId = meResponse.data?.id;
if (!userId) {
throw new Error('Could not get user ID');
}
//Makes api call
const deleteBookmark = await client.users.deleteBookmark(userId, tweetId);
console.dir(deleteBookmark, {
depth: null,
});
process.exit();
} catch (error) {
console.log(error);
process.exit(-1);
}
})();
================================================
FILE: javascript/users/bookmark/get_bookmarks.js
================================================
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
//Helper function to parse callback
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
//Helper terminal input function
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const CLIENT_ID = process.env.CLIENT_ID;
const CLIENT_SECRET = process.env.CLIENT_SECRET;
// Optional parameters for additional payload data
const params = {
expansions: ['author_id'],
userFields: ['username', 'created_at'],
tweetFields: ['geo', 'entities', 'context_annotations']
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'bookmark.read']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const STATE = "my-state";
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(STATE);
console.log(`Please go here and authorize:`, authUrl);
//Input users callback url in terminal
const redirectCallback = await input("Paste the redirected callback here: ");
//Parse callback
const { state, code } = getQueryStringParams(redirectCallback);
if (state !== STATE) {
console.log("State isn't matching");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
//Get the user ID
const meResponse = await client.users.getMe();
const userId = meResponse.data?.id;
if (!userId) {
throw new Error('Could not get user ID');
}
//Makes api call
const getBookmark = await client.users.getBookmarks(userId, params);
console.dir(getBookmark, {
depth: null,
});
process.exit();
} catch (error) {
console.log(error);
process.exit(-1);
}
})();
================================================
FILE: javascript/users/follow/get_followers.js
================================================
// Fetch the followers of a user account, by ID
// https://developer.twitter.com/en/docs/twitter-api/users/follows/quick-start
const { Client, UserPaginator } = require('@xdevplatform/xdk');
// this is the ID for @XDevelopers
const userId = '2244994945';
const bearerToken = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: bearerToken });
const getFollowers = async () => {
console.log("Retrieving followers...");
// Use paginator for automatic pagination
const followers = new UserPaginator(
async (token) => {
const res = await client.users.getFollowers(userId, {
maxResults: 1000,
paginationToken: token,
userFields: ['created_at']
});
return {
data: res.data ?? [],
meta: res.meta,
includes: res.includes,
errors: res.errors
};
}
);
// Fetch all pages
await followers.fetchNext();
while (!followers.done) {
await followers.fetchNext();
}
console.log(followers.users);
console.log(`Got ${followers.users.length} users.`);
}
getFollowers().catch(err => {
console.error('Error:', err);
process.exit(-1);
});
================================================
FILE: javascript/users/follow/get_followers_paginated.js
================================================
/**
* User Followers Lookup (Paginated) - X API v2
*
* Endpoint: GET https://api.x.com/2/users/:id/followers
* Docs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers
*
* Authentication: Bearer Token (App-only) or OAuth (User Context)
* Required env vars: BEARER_TOKEN
*
* This example demonstrates automatic pagination using UserPaginator
* to fetch all pages of results. For a simple single-request example,
* see followers_lookup.js
*/
const { Client, UserPaginator } = require('@xdevplatform/xdk');
// this is the ID for @XDevelopers
const userId = '2244994945';
const bearerToken = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: bearerToken });
const getFollowers = async () => {
console.log("Retrieving followers...");
// Use paginator for automatic pagination
const followers = new UserPaginator(
async (token) => {
const res = await client.users.getFollowers(userId, {
maxResults: 1000,
paginationToken: token,
userFields: ['created_at']
});
return {
data: res.data ?? [],
meta: res.meta,
includes: res.includes,
errors: res.errors
};
}
);
// Fetch all pages
await followers.fetchNext();
while (!followers.done) {
await followers.fetchNext();
}
console.log(followers.users);
console.log(`Got ${followers.users.length} users.`);
}
getFollowers().catch(err => {
console.error('Error:', err);
process.exit(-1);
});
================================================
FILE: javascript/users/follow/get_following_paginated.js
================================================
/**
* User Following Lookup (Paginated) - X API v2
*
* Endpoint: GET https://api.x.com/2/users/:id/following
* Docs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following
*
* Authentication: Bearer Token (App-only) or OAuth (User Context)
* Required env vars: BEARER_TOKEN
*
* This example demonstrates automatic pagination using UserPaginator
* to fetch all pages of results.
*/
const { Client, UserPaginator } = require('@xdevplatform/xdk');
// this is the ID for @XDevelopers
const userId = '2244994945';
const bearerToken = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: bearerToken });
const getFollowing = async () => {
console.log("Retrieving users this user is following...");
// Use paginator for automatic pagination
const following = new UserPaginator(
async (token) => {
const res = await client.users.getFollowing(userId, {
maxResults: 1000,
paginationToken: token,
userFields: ['created_at']
});
return {
data: res.data ?? [],
meta: res.meta,
includes: res.includes,
errors: res.errors
};
}
);
// Fetch all pages
await following.fetchNext();
while (!following.done) {
await following.fetchNext();
}
console.log(following.users);
console.log(`Got ${following.users.length} users.`);
}
getFollowing().catch(err => {
console.error('Error:', err);
process.exit(-1);
});
================================================
FILE: javascript/users/get_users_by_usernames.js
================================================
/**
* User Lookup - X API v2
*
* Endpoint: GET https://api.x.com/2/users/by
* Docs: https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by
*
* Authentication: Bearer Token (App-only) or OAuth (User Context)
* Required env vars: BEARER_TOKEN
*/
const { Client } = require('@xdevplatform/xdk');
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
const usernames = ['XDevelopers', 'X'];
(async () => {
try {
// Usernames to look up (up to 100)
const response = await client.users.getByUsernames(usernames, {
userFields: ['created_at', 'description', 'public_metrics'],
expansions: ['pinned_tweet_id']
});
console.dir(response, { depth: null });
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/get_users_by_usernames_user_context.js
================================================
// Get User objects by username, using user authentication
// https://developer.twitter.com/en/docs/twitter-api/users/lookup/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// These are the parameters for the API request
// specify usernames to fetch, and any additional fields that are required
// by default, only the User ID, name and username are returned
const usernames = ['XDevelopers', 'X']; // Edit usernames to look up
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log('Please go here and authorize:', authUrl);
// Input callback URL from terminal
const redirectCallback = await input('Paste the redirected callback URL here: ');
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.getByUsernames(usernames, {
userFields: ['created_at', 'description'],
expansions: ['pinned_tweet_id']
});
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/get_users_me.js
================================================
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log('Please go here and authorize:', authUrl);
// Input callback URL from terminal
const redirectCallback = await input('Paste the redirected callback URL here: ');
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK - get authenticated user
const response = await client.users.getMe({
userFields: ['created_at', 'description'],
expansions: ['pinned_tweet_id']
});
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/like/get_liked_posts.js
================================================
// Get Liked Posts by User ID using OAuth 2.0 to authorize the user
// https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-users-id-liked_tweets
const {
Client,
OAuth2,
PostPaginator,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// You can replace the ID given with the User ID you wish to get liked posts for.
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'like.read', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
console.log("Retrieving liked posts...");
// Use paginator for automatic pagination
const likedPosts = new PostPaginator(
async (token) => {
const res = await client.users.getLikedPosts(userId, {
maxResults: 100,
paginationToken: token,
tweetFields: ['lang', 'author_id'],
userFields: ['created_at']
});
return {
data: res.data ?? [],
meta: res.meta,
includes: res.includes,
errors: res.errors
};
}
);
// Fetch all pages
await likedPosts.fetchNext();
while (!likedPosts.done) {
await likedPosts.fetchNext();
}
console.dir(likedPosts.posts, {
depth: null
});
console.log(`Got ${likedPosts.posts.length} liked posts for user ID ${userId}!`);
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/like/like_post.js
================================================
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticating user
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
// You can replace Post ID given with the Post ID you wish to like.
// You can find a Post ID by using the Post lookup endpoint
const postId = "1354143047324299264";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access', 'like.write']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log('Please go here and authorize:', authUrl);
// Input callback URL from terminal
const redirectCallback = await input('Paste the redirected callback URL here: ');
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.likePost(userId, {body: {tweet_id: postId}});
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/like/unlike_post.js
================================================
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticating user
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
// You can replace Post ID given with the Post ID you wish to unlike.
// You can find a Post ID by using the Post lookup endpoint
const postId = "1354143047324299264";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access', 'like.write']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log('Please go here and authorize:', authUrl);
// Input callback URL from terminal
const redirectCallback = await input('Paste the redirected callback URL here: ');
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.unlikePost(userId, postId);
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/lists/follow_list.js
================================================
// Follow a list using OAuth 2.0 to authorize the user
// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticated user
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
// Be sure to add replace list-id-to-follow with the list id you wish to follow.
const listId = "list-id-to-follow";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.followList(userId, {body: {list_id: listId}});
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/lists/get_followed_lists.js
================================================
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
const id = "user-id";
(async () => {
try {
// These are the parameters for the API request
// by default, only the List ID and name are returned
const response = await client.users.getFollowedLists(id, {
listFields: ['owner_id'], // Edit optional query parameters here
expansions: ['owner_id'], // expansions is used to include the user object
userFields: ['created_at', 'verified'] // Edit optional query parameters here
});
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/lists/get_list_memberships.js
================================================
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
const id = "user-id";
(async () => {
try {
// These are the parameters for the API request
// by default, only the List ID and name are returned
const response = await client.users.getListMemberships(id, {
listFields: ['owner_id'], // Edit optional query parameters here
expansions: ['owner_id'], // expansions is used to include the user object
userFields: ['created_at', 'verified'] // Edit optional query parameters here
});
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/lists/get_owned_lists.js
================================================
const { Client } = require('@xdevplatform/xdk');
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
const id = "user-id";
(async () => {
try {
// These are the parameters for the API request
// by default, only the List ID and name are returned
const response = await client.users.getOwnedLists(id, {
listFields: ['owner_id'], // Edit optional query parameters here
expansions: ['owner_id'], // expansions is used to include the user object
userFields: ['created_at', 'verified'] // Edit optional query parameters here
});
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/lists/pin_list.js
================================================
// Pin a list using OAuth 2.0 to authorize the user
// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticated user
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
// Be sure to add replace list-id-to-pin with the list id you wish to pin.
const listId = "list-id-to-pin";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.pinList(userId, {list_id: listId});
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/lists/unfollow_list.js
================================================
// Unfollow a list using OAuth 2.0 to authorize the user
// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticated user
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
// Be sure to replace list-id-to-unfollow with the list id you wish to unfollow.
const listId = "list-id-to-unfollow";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.unfollowList(userId, listId);
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/lists/unpin_list.js
================================================
// Unpin a list using OAuth 2.0 to authorize the user
// https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticated user
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
// Be sure to replace list-id-to-unpin with the list id you wish to unpin.
const listId = "list-id-to-unpin";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'list.read', 'list.write', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.unpinList(userId, listId);
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/mute/get_muting.js
================================================
// Retrieve accounts muted by authenticated user
// https://developer.twitter.com/en/docs/twitter-api/users/mutes/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticated user
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access', 'mute.read']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.getMuting(userId);
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/mute/mute_user.js
================================================
// mute a user, using user authentication
// https://developer.twitter.com/en/docs/twitter-api/users/mutes/quick-start
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticated user
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
// Be sure to add replace id-to-mute with the user id you wish to mute.
// You can find a user ID by using the user lookup endpoint
const targetUserId = "id-to-mute";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access', 'mute.write']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log('Please go here and authorize:', authUrl);
// Input callback URL from terminal
const redirectCallback = await input('Paste the redirected callback URL here: ');
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.muteUser(userId, { body: { target_user_id: targetUserId } });
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/mute/unmute_user.js
================================================
// Unmute a user, using user authentication
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticated user
// You can find a user ID by using the user lookup endpoint
const sourceUserId = "your-user-id";
// Be sure to add replace the id-to-unmute with the user id of the you wish to unmute.
// You can find a user ID by using the user lookup endpoint
const targetUserId = "id-to-unmute";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access', 'mute.write']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log('Please go here and authorize:', authUrl);
// Input callback URL from terminal
const redirectCallback = await input('Paste the redirected callback URL here: ');
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.unmuteUser(sourceUserId, targetUserId);
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/repost/repost_post.js
================================================
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticated user
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
// You can replace the given Post ID with the Post ID you want to repost
// You can find a Post ID by using the Post lookup endpoint
const postId = "1412865600439738368";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log('Please go here and authorize:', authUrl);
// Input callback URL from terminal
const redirectCallback = await input('Paste the redirected callback URL here: ');
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.repostPost(userId, { body: { tweet_id: postId } });
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/repost/unrepost_post.js
================================================
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticating user
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
// You can replace the given Post ID with the Post ID you want to undo repost
// You can find a Post ID by using the Post lookup endpoint
const sourceTweetId = "1412865600439738368";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'tweet.write', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log('Please go here and authorize:', authUrl);
// Input callback URL from terminal
const redirectCallback = await input('Paste the redirected callback URL here: ');
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.unrepostPost(userId, sourceTweetId);
console.dir(response, {
depth: null
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/timeline/get_home_timeline.js
================================================
// Get reverse chronological home timeline
// https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-reverse-chronological-timeline
const {
Client,
OAuth2,
generateCodeVerifier,
generateCodeChallenge
} = require('@xdevplatform/xdk');
const readline = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
// The code below sets the client ID and client secret from your environment variables
// To set environment variables on macOS or Linux, run the export commands below from the terminal:
// export CLIENT_ID='YOUR-CLIENT-ID'
// export CLIENT_SECRET='YOUR-CLIENT-SECRET'
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
// Be sure to replace your-user-id with your own user ID or one of an authenticated user
// You can find a user ID by using the user lookup endpoint
const userId = "your-user-id";
async function input(prompt) {
return new Promise((resolve) => {
readline.question(prompt, (out) => {
readline.close();
resolve(out);
});
});
}
// Helper function to parse callback URL
const getQueryStringParams = (query) => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split(/[\?\&]/)
.reduce((params, param) => {
let [key, value] = param.split("=");
params[key] = value
? decodeURIComponent(value.replace(/\+/g, " "))
: "";
return params;
}, {})
: {};
};
(async () => {
try {
// Configure OAuth 2.0
const oauth2Config = {
clientId: clientId,
clientSecret: clientSecret,
redirectUri: 'https://example.com',
scope: ['tweet.read', 'users.read', 'offline.access']
};
const oauth2 = new OAuth2(oauth2Config);
// Generate PKCE parameters
const state = 'example-state';
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
oauth2.setPkceParameters(codeVerifier, codeChallenge);
// Get authorization URL
const authUrl = await oauth2.getAuthorizationUrl(state);
console.log("Please go here and authorize:", authUrl);
// Input callback URL from terminal
const redirectCallback = await input("Paste the redirected callback URL here: ");
// Parse callback
const { state: returnedState, code } = getQueryStringParams(redirectCallback);
if (returnedState !== state) {
console.log("State doesn't match");
process.exit(-1);
}
// Exchange code for tokens
const tokens = await oauth2.exchangeCode(code, codeVerifier);
// Create client with access token
const client = new Client({
accessToken: tokens.access_token
});
// Make the request using SDK
const response = await client.users.getTimeline(userId);
console.dir(response, {
depth: null,
});
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/timeline/get_mentions.js
================================================
// Get User mentions timeline by user ID
// https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/quick-start
const { Client, PostPaginator } = require('@xdevplatform/xdk');
const userId = '2244994945';
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const bearerToken = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: bearerToken });
// this is the ID for @TwitterDev
const getUserMentions = async () => {
console.log("Retrieving mentions...");
// Use paginator for automatic pagination
const userMentions = new PostPaginator(
async (token) => {
const res = await client.users.getMentions(userId, {
maxResults: 100,
paginationToken: token,
tweetFields: ['created_at']
});
return {
data: res.data ?? [],
meta: res.meta,
includes: res.includes,
errors: res.errors
};
}
);
// Fetch all pages
await userMentions.fetchNext();
while (!userMentions.done) {
await userMentions.fetchNext();
}
console.dir(userMentions.posts, {
depth: null
});
console.log(`Got ${userMentions.posts.length} mentions for user ID ${userId}!`);
}
getUserMentions().catch(err => {
console.error('Error:', err);
process.exit(-1);
});
================================================
FILE: javascript/users/timeline/get_posts.js
================================================
/**
* User Posts Timeline - X API v2
*
* Endpoint: GET https://api.x.com/2/users/:id/posts
* Docs: https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets
*
* Authentication: Bearer Token (App-only) or OAuth (User Context)
* Required env vars: BEARER_TOKEN
*
* This is a simple example that makes a single request.
* For automatic pagination, see user_posts_paginated.js
*/
const { Client } = require('@xdevplatform/xdk');
const token = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: token });
// Replace with the user ID you want to get posts for
const userId = "2244994945";
(async () => {
try {
const response = await client.users.getPosts(userId, {
tweetFields: ['created_at', 'public_metrics'],
maxResults: 10
});
console.dir(response, { depth: null });
} catch (e) {
console.log(e);
process.exit(-1);
}
process.exit();
})();
================================================
FILE: javascript/users/timeline/get_posts_paginated.js
================================================
/**
* User Posts Timeline (Paginated) - X API v2
*
* Endpoint: GET https://api.x.com/2/users/:id/posts
* Docs: https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets
*
* Authentication: Bearer Token (App-only) or OAuth (User Context)
* Required env vars: BEARER_TOKEN
*
* This example demonstrates automatic pagination using PostPaginator
* to fetch all pages of results. For a simple single-request example,
* see user_posts.js
*/
const { Client, PostPaginator } = require('@xdevplatform/xdk');
// this is the ID for @TwitterDev
const userId = "2244994945";
// The code below sets the bearer token from your environment variables
// To set environment variables on macOS or Linux, run the export command below from the terminal:
// export BEARER_TOKEN='YOUR-TOKEN'
const bearerToken = process.env.BEARER_TOKEN;
const client = new Client({ bearerToken: bearerToken });
const getUserTweets = async () => {
console.log("Retrieving Tweets...");
// Use paginator for automatic pagination
// we request the author_id expansion so that we can print out the user name later
const userTweets = new PostPaginator(
async (token) => {
const res = await client.users.getPosts(userId, {
maxResults: 100,
paginationToken: token,
tweetFields: ['created_at'],
expansions: ['author_id']
});
return {
data: res.data ?? [],
meta: res.meta,
includes: res.includes,
errors: res.errors
};
}
);
// Fetch all pages
await userTweets.fetchNext();
while (!userTweets.done) {
await userTweets.fetchNext();
}
let userName;
if (userTweets.includes?.users && userTweets.includes.users.length > 0) {
userName = userTweets.includes.users[0].username;
}
console.dir(userTweets.posts, {
depth: null
});
console.log(`Got ${userTweets.posts.length} Tweets from ${userName || 'user'} (user ID ${userId})!`);
}
getUserTweets().catch(err => {
console.error('Error:', err);
process.exit(-1);
});
================================================
FILE: llms.txt
================================================
# X API v2 Sample Code Repository
> This file provides context for LLMs (Large Language Models) to understand and navigate this codebase.
## Purpose
This repository contains working code examples for the X (formerly Twitter) API v2. Examples are provided in Python, JavaScript (Node.js), Ruby, and Java.
## Repository Structure
```
/
├── python/ # Python examples
│ ├── posts/ # Create, delete, search, lookup posts
│ ├── users/ # User lookup, followers, blocks, mutes
│ ├── timelines/ # User posts, mentions, home timeline
│ ├── streams/ # Filtered and sampled streams
│ ├── bookmarks/ # Bookmark management
│ ├── spaces/ # Spaces lookup and search
│ ├── lists/ # List management
│ ├── direct_messages/ # DM lookup and sending
│ ├── media/ # Media upload
│ ├── compliance/ # Batch compliance jobs
│ └── usage/ # API usage stats
├── javascript/ # JavaScript (Node.js) examples
├── ruby/ # Ruby examples
├── java/ # Java examples
└── docs/ # Endpoint documentation (language-agnostic)
```
## File Naming Conventions
- Python: `snake_case.py` (e.g., `create_post.py`)
- JavaScript: `snake_case.js` (e.g., `create_post.js`)
- Ruby: `snake_case.rb` (e.g., `search_recent.rb`)
- Java: `PascalCase.java` (e.g., `SearchRecent.java`)
## Authentication Types
1. **Bearer Token** (App-only): For read-only endpoints that don't require user context
- Env var: `BEARER_TOKEN`
2. **OAuth 1.0a** (User Context): For endpoints that act on behalf of a user
- Env vars: `CONSUMER_KEY`, `CONSUMER_SECRET`
3. **OAuth 2.0 with PKCE** (User Context): For newer endpoints like bookmarks
- Requires OAuth 2.0 flow to get user access token
## API Base URL
All endpoints use: `https://api.x.com/2/`
## Key Terminology (Rebrand)
| Old Term | New Term |
|----------|----------|
| Tweet | Post |
| Retweet | Repost |
| Twitter | X |
| TwitterDev | XDevelopers |
Note: The API endpoints still use `/tweets/` in the URL path for backwards compatibility.
## Common Operations by Category
### Posts (formerly Tweets)
- `POST /2/tweets` - Create a post
- `DELETE /2/tweets/:id` - Delete a post
- `GET /2/tweets` - Look up posts by ID
- `GET /2/tweets/search/recent` - Search recent posts (7 days)
- `GET /2/tweets/search/all` - Search all posts (Academic access)
- `GET /2/tweets/counts/recent` - Count recent posts
- `GET /2/tweets/:id/quote_tweets` - Get quote posts
- `POST /2/users/:id/retweets` - Repost
- `DELETE /2/users/:id/retweets/:tweet_id` - Undo repost
### Users
- `GET /2/users/by` - Look up users by username
- `GET /2/users/me` - Get authenticated user
- `GET /2/users/:id/followers` - Get followers
- `GET /2/users/:id/following` - Get following
- `POST /2/users/:id/blocking` - Block user
- `POST /2/users/:id/muting` - Mute user
### Timelines
- `GET /2/users/:id/tweets` - User's posts
- `GET /2/users/:id/mentions` - User's mentions
- `GET /2/users/:id/reverse_chronological_timeline` - Home timeline
### Streams (Real-time)
- `GET /2/tweets/search/stream` - Filtered stream
- `GET /2/tweets/sample/stream` - 1% sampled stream
### Likes
- `POST /2/users/:id/likes` - Like a post
- `DELETE /2/users/:id/likes/:tweet_id` - Unlike a post
- `GET /2/tweets/:id/liking_users` - Users who liked
- `GET /2/users/:id/liked_tweets` - Posts user liked
### Bookmarks
- `GET /2/users/:id/bookmarks` - Get bookmarks
- `POST /2/users/:id/bookmarks` - Create bookmark
- `DELETE /2/users/:id/bookmarks/:tweet_id` - Delete bookmark
### Lists
- `GET /2/lists/:id` - Look up list
- `POST /2/lists` - Create list
- `DELETE /2/lists/:id` - Delete list
### Spaces
- `GET /2/spaces` - Look up Spaces by ID
- `GET /2/spaces/search` - Search Spaces
### Direct Messages
- `GET /2/dm_events` - Get DM events
- `POST /2/dm_conversations/with/:participant_id/messages` - Send DM
## Quick Start
1. Get API credentials at https://developer.x.com/portal
2. Set environment variables:
```bash
export BEARER_TOKEN='your_token'
export CONSUMER_KEY='your_key'
export CONSUMER_SECRET='your_secret'
```
3. Navigate to desired language folder
4. Install dependencies (see language-specific README)
5. Run example
## Dependencies by Language
### Python
```bash
pip install requests requests-oauthlib
```
### JavaScript
```bash
npm install needle got oauth-1.0a
```
### Ruby
```bash
gem install typhoeus oauth
```
### Java
- Apache HttpClient 4.5+
- Gson 2.9+
## External Resources
- API Documentation: https://developer.x.com/en/docs/twitter-api
- Developer Portal: https://developer.x.com/en/portal/dashboard
- API Reference: https://developer.x.com/en/docs/api-reference-index
================================================
FILE: python/README.md
================================================
# X API v2 - Python Examples
Working Python examples for the X API v2.
## Setup
```bash
pip install -r requirements.txt
```
The `requirements.txt` file includes:
- `xdk>=0.4.5` - X Developer Kit for Python
## Environment Variables
**For read-only operations (search, lookup):**
```bash
export BEARER_TOKEN='your_bearer_token'
```
**For user actions (post, like, repost, bookmark, mute, etc.):**
```bash
export CLIENT_ID='your_client_id'
export CLIENT_SECRET='your_client_secret'
```
**Note:** Most user action examples (create post, like, repost, bookmark, mute, block, etc.) require OAuth 2.0 authentication with `CLIENT_ID` and `CLIENT_SECRET`. Read-only examples (search, lookup) only require `BEARER_TOKEN`.
## Examples
### Posts
- `posts/create_post.py` - Create a new post (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `posts/delete_post.py` - Delete a post (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `posts/get_liking_users.py` - Get users who liked a post
- `posts/get_post_counts_all.py` - Get post counts (full archive)
- `posts/get_post_counts_recent.py` - Get post counts (recent)
- `posts/get_posts_by_ids.py` - Look up posts by ID
- `posts/get_quoted_posts.py` - Get posts that quote a post
- `posts/get_reposted_by.py` - Get users who reposted a post
- `posts/search_all.py` - Full archive search
- `posts/search_recent.py` - Recent search (last 7 days)
### Users
- `users/get_users_by_usernames.py` - Look up users by username (bearer token)
- `users/get_users_by_usernames_user_context.py` - Look up user by username (user context) (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/get_users_me.py` - Get authenticated user (me) (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Block
- `users/block/get_blocking.py` - Get users blocked by a user (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Bookmark
- `users/bookmark/get_bookmarks.py` - Get user's bookmarks (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/bookmark/create_bookmark.py` - Create a bookmark (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/bookmark/delete_bookmark.py` - Delete a bookmark (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Follow
- `users/follow/get_followers.py` - Get user's followers
- `users/follow/get_following.py` - Get users a user is following
#### User Actions - Like
- `users/like/get_liked_posts.py` - Get posts liked by a user (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/like/like_post.py` - Like a post (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/like/unlike_post.py` - Unlike a post (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Lists
- `users/lists/follow_list.py` - Follow a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/lists/get_followed_lists.py` - Get lists followed by a user
- `users/lists/get_list_memberships.py` - Get list memberships
- `users/lists/get_owned_lists.py` - Get lists owned by a user
- `users/lists/get_pinned_lists.py` - Get pinned lists (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/lists/pin_list.py` - Pin a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/lists/unfollow_list.py` - Unfollow a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/lists/unpin_list.py` - Unpin a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Mute
- `users/mute/get_muting.py` - Get users muted by a user (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/mute/mute_user.py` - Mute a user (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/mute/unmute_user.py` - Unmute a user (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Repost
- `users/repost/repost_post.py` - Repost a post (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `users/repost/unrepost_post.py` - Undo a repost (requires `CLIENT_ID`, `CLIENT_SECRET`)
#### User Actions - Timeline
- `users/timeline/get_mentions.py` - Get user mentions timeline
- `users/timeline/get_posts.py` - Get user's posts timeline
- `users/timeline/get_home_timeline.py` - Get home timeline (requires `CLIENT_ID`, `CLIENT_SECRET`)
### Streams
- `streams/stream_posts_filtered.py` - Filtered stream with rules
- `streams/stream_posts_sample.py` - Sampled stream
### Lists
- `lists/add_member.py` - Add member to a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `lists/create_list.py` - Create a new list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `lists/delete_list.py` - Delete a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `lists/get_list_by_id.py` - Get list by ID
- `lists/get_list_followers.py` - Get list followers
- `lists/get_list_members.py` - Get list members
- `lists/get_list_posts.py` - Get posts from a list
- `lists/remove_member.py` - Remove member from a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `lists/update_list.py` - Update a list (requires `CLIENT_ID`, `CLIENT_SECRET`)
### Spaces
- `spaces/get_spaces_by_ids.py` - Look up Spaces by ID
- `spaces/search_spaces.py` - Search for Spaces
### Direct Messages
- `direct_messages/get_events_by_conversation.py` - Get DM events by conversation (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `direct_messages/get_one_to_one_conversation_events.py` - Get one-to-one conversation events (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `direct_messages/get_user_conversation_events.py` - Get user conversation events (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `direct_messages/post_dm_to_conversation.py` - Post DM to conversation (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `direct_messages/post_group_conversation_dm.py` - Post group conversation DM (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `direct_messages/post_one_to_one_dm.py` - Post one-to-one DM (requires `CLIENT_ID`, `CLIENT_SECRET`)
### Media
- `media/media_upload_v2.py` - Media upload v2 (requires `CLIENT_ID`, `CLIENT_SECRET`)
- `media/upload.py` - Media upload (requires `CLIENT_ID`, `CLIENT_SECRET`)
### Compliance
- `compliance/create_jobs.py` - Create compliance job
- `compliance/download_results.py` - Download compliance results
- `compliance/get_jobs_by_id.py` - Get compliance job by ID
- `compliance/get_jobs.py` - Get compliance jobs
- `compliance/upload_ids.py` - Upload IDs for compliance
### Usage
- `usage/get_usage.py` - Get API usage information
## Running Examples
```bash
# Make sure environment variables are set
python posts/search_recent.py
```
## More Information
- [X API Documentation](https://developer.x.com/en/docs/twitter-api)
- [X Developer Portal](https://developer.x.com/en/portal/dashboard)
================================================
FILE: python/activity/create_subscription.py
================================================
"""
Create Activity Subscription - X API v2
========================================
Endpoint: POST https://api.x.com/2/activity/subscriptions
Docs: https://docs.x.com/x-api/activity/introduction
Creates a subscription to receive real-time activity events for a specified
event type and filter. Once created, matching events will be delivered to the
activity stream (see stream_events.py) and optionally to a registered webhook.
Supported public event types include:
- profile.update.bio
- profile.update.picture
- profile.update.banner
- profile.update.location
- profile.update.url
- profile.update.username
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with the user ID you want to monitor for activity events
user_id = "2244994945"
# Replace with the event type you want to subscribe to.
# See the supported event types listed in the docstring above.
event_type = "profile.update.bio"
# Optional: replace with a registered webhook ID to also receive events via webhook delivery.
# If omitted, events are only available on the activity stream.
webhook_id = None
def main():
payload = {
"event_type": event_type,
"filter": {
"user_id": user_id
}
}
# Attach a label to help identify this subscription in the stream
payload["tag"] = f"{event_type} for user {user_id}"
# Optionally route events to a registered webhook in addition to the stream
if webhook_id:
payload["webhook_id"] = webhook_id
response = client.activity.create_subscription(body=payload)
print("Response code: 201")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/activity/delete_subscription.py
================================================
"""
Delete Activity Subscription - X API v2
========================================
Endpoint: DELETE https://api.x.com/2/activity/subscriptions/:id
Docs: https://docs.x.com/x-api/activity/introduction
Deletes an activity subscription. Once deleted, events matching that subscription
will no longer be delivered to the stream or associated webhook. Use
list_subscriptions.py to find the subscription_id you wish to remove.
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with the subscription ID you wish to delete.
# You can find subscription IDs by running list_subscriptions.py
subscription_id = "your-subscription-id"
def main():
response = client.activity.delete_subscription(subscription_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/activity/list_subscriptions.py
================================================
"""
List Activity Subscriptions - X API v2
=======================================
Endpoint: GET https://api.x.com/2/activity/subscriptions
Docs: https://docs.x.com/x-api/activity/introduction
Returns all active activity subscriptions for your app. Use the subscription_id
from the response to update or delete individual subscriptions.
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
def main():
response = client.activity.get_subscriptions()
# Access data attribute safely
response_data = getattr(response, 'data', None)
if response_data:
print(json.dumps(response_data, indent=4, sort_keys=True))
else:
print(json.dumps(response, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/activity/stream_events.py
================================================
"""
Activity Stream - X API v2
==========================
Endpoint: GET https://api.x.com/2/activity/stream
Docs: https://docs.x.com/x-api/activity/introduction
Opens a persistent HTTP connection and streams real-time activity events
matching your active subscriptions. Events are delivered as they occur on
the platform — no polling required.
You must create at least one subscription (see create_subscription.py) before
events will be delivered to this stream.
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
def main():
print("Connecting to activity stream... (press Ctrl+C to stop)")
# The stream() method returns a generator that yields events as they arrive.
# The SDK manages reconnection with exponential backoff automatically.
for event in client.activity.stream():
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
event_data = getattr(event, 'data', None)
if event_data:
print(json.dumps(event_data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/activity/update_subscription.py
================================================
"""
Update Activity Subscription - X API v2
========================================
Endpoint: PUT https://api.x.com/2/activity/subscriptions/:id
Docs: https://docs.x.com/x-api/activity/introduction
Updates an existing activity subscription. You can change the filter (e.g. target
a different user ID), the tag, or the associated webhook. Use list_subscriptions.py
to find the subscription_id you wish to update.
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with the subscription ID you wish to update.
# You can find subscription IDs by running list_subscriptions.py
subscription_id = "your-subscription-id"
# Replace with the updated user ID you want to monitor
updated_user_id = "2244994945"
def main():
payload = {
"filter": {
"user_id": updated_user_id
}
}
response = client.activity.update_subscription(subscription_id, body=payload)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/compliance/create_jobs.py
================================================
"""
Create Compliance Job - X API v2
================================
Endpoint: POST https://api.x.com/2/compliance/jobs
Docs: https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# For User Compliance Job, replace the type value with users instead of tweets
# Also replace the name value with your desired job name
payload = {"type": "tweets", "name": "my_batch_compliance_job"}
def main():
response = client.compliance.create_job(body=payload)
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/compliance/download_results.py
================================================
"""
Download Compliance Results - X API v2
======================================
Endpoint: GET (provided in compliance job response)
Docs: https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs-id
Note: This endpoint uses a pre-signed URL from the compliance job response.
The download_url is provided when you check the status of a compliance job.
"""
import requests
# Replace with your job download_url (from the compliance job response)
download_url = ''
def main():
response = requests.get(download_url)
print(f"Response code: {response.status_code}")
if response.status_code != 200:
raise Exception(response.status_code, response.text)
entries = response.text.splitlines()
for entry in entries:
print(entry)
if __name__ == "__main__":
main()
================================================
FILE: python/compliance/get_jobs.py
================================================
"""
Get Compliance Jobs - X API v2
==============================
Endpoint: GET https://api.x.com/2/compliance/jobs
Docs: https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Type can be "tweets" or "users"
job_type = "tweets"
def main():
response = client.compliance.get_jobs(type=job_type)
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/compliance/get_jobs_by_id.py
================================================
"""
Get Compliance Job by ID - X API v2
===================================
Endpoint: GET https://api.x.com/2/compliance/jobs/:id
Docs: https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs-id
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with your job ID below
job_id = ''
def main():
response = client.compliance.get_job(job_id)
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/compliance/upload_ids.py
================================================
"""
Upload IDs for Compliance Job - X API v2
========================================
Endpoint: PUT (provided in compliance job response)
Docs: https://developer.x.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs
Note: This endpoint uses a pre-signed URL from the compliance job response.
The upload_url is provided when you create a compliance job.
"""
import os
import requests
# Replace with your job upload_url (from the compliance job response)
upload_url = ''
# Replace with your file path that contains the list of Tweet IDs or User IDs, one ID per line
file_path = ''
def main():
headers = {'Content-Type': "text/plain"}
with open(file_path, 'rb') as f:
response = requests.put(upload_url, data=f, headers=headers)
print(f"Response code: {response.status_code}")
if response.status_code != 200:
raise Exception(response.status_code, response.text)
print(response.text)
if __name__ == "__main__":
main()
================================================
FILE: python/direct_messages/get_events_by_conversation.py
================================================
"""
Get Events by Conversation ID - X API v2
=========================================
Endpoint: GET https://api.x.com/2/dm_conversations/:dm_conversation_id/dm_events
Docs: https://developer.x.com/en/docs/twitter-api/direct-messages/lookup/api-reference/get-dm-conversations-dm_conversation_id-dm_events
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
This example retrieves Direct Message events by conversation ID.
This supports both one-to-one and group conversations.
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["dm.read", "tweet.read", "users.read", "offline.access"]
# What is the ID of the conversation to retrieve?
dm_conversation_id = "1512210732774948865"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get events by conversation ID with automatic pagination
all_events = []
for page in client.direct_messages.get_events_by_conversation_id(
dm_conversation_id,
max_results=100
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_events.extend(page_data)
print(f"Fetched {len(page_data)} events (total: {len(all_events)})")
print(f"\nTotal Conversation Events: {len(all_events)}")
print(json.dumps({"data": all_events[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/direct_messages/get_one_to_one_conversation_events.py
================================================
"""
Get One-to-One Conversation Events - X API v2
=============================================
Endpoint: GET https://api.x.com/2/dm_conversations/with/:participant_id/dm_events
Docs: https://developer.x.com/en/docs/twitter-api/direct-messages/lookup/api-reference/get-dm-conversations-with-participant_id-dm_events
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
This example retrieves Direct Message conversation events associated with a one-to-one message.
Currently, the v2 DM endpoints support three conversation event types: MessageCreate, ParticipantsJoin, and ParticipantsLeave.
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["dm.read", "tweet.read", "users.read", "offline.access"]
# Who is this one-to-one conversation with?
participant_id = "1716450569358098432"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get one-to-one conversation events with automatic pagination
all_events = []
for page in client.direct_messages.get_events_by_participant_id(
participant_id,
max_results=100
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_events.extend(page_data)
print(f"Fetched {len(page_data)} events (total: {len(all_events)})")
print(f"\nTotal Conversation Events: {len(all_events)}")
print(json.dumps({"data": all_events[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/direct_messages/get_user_conversation_events.py
================================================
"""
Get User Conversation Events - X API v2
=======================================
Endpoint: GET https://api.x.com/2/dm_events
Docs: https://developer.x.com/en/docs/twitter-api/direct-messages/lookup/api-reference/get-dm-events
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
This example retrieves Direct Message events of the authenticating user.
This supports both one-to-one and group conversations.
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["dm.read", "tweet.read", "users.read", "offline.access"]
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get user conversation events with automatic pagination
# DM event fields are adjustable. Options include:
# id, text, event_type, created_at, dm_conversation_id,
# sender_id, participant_ids, referenced_tweets, attachments
all_events = []
for page in client.direct_messages.get_events(
max_results=100,
dm_event_fields=["id", "text", "event_type", "created_at", "sender_id"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_events.extend(page_data)
print(f"Fetched {len(page_data)} events (total: {len(all_events)})")
print(f"\nTotal DM Events: {len(all_events)}")
print(json.dumps({"data": all_events[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/direct_messages/post_dm_to_conversation.py
================================================
"""
Post DM to Conversation - X API v2
===================================
Endpoint: POST https://api.x.com/2/dm_conversations/:dm_conversation_id/messages
Docs: https://developer.x.com/en/docs/twitter-api/direct-messages/manage/api-reference/post-dm-conversations-dm_conversation_id-messages
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["dm.read", "dm.write", "tweet.read", "users.read", "offline.access"]
# Provide the ID of the conversation this message should be added to.
dm_conversation_id = "1856843062712176900"
# Set the text of the message to be sent.
text_message = "Hi, I am adding a message to an existing conversation by referencing its ID."
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Add DM to conversation
payload = {"text": text_message}
response = client.direct_messages.create_by_conversation_id(dm_conversation_id, body=payload)
print("Response code: 201")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/direct_messages/post_group_conversation_dm.py
================================================
"""
Post Group Conversation Direct Message - X API v2
=================================================
Endpoint: POST https://api.x.com/2/dm_conversations
Docs: https://developer.x.com/en/docs/twitter-api/direct-messages/manage/api-reference/post-dm-conversations
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["dm.read", "dm.write", "tweet.read", "users.read", "offline.access"]
# Who is in this group conversation? Reference their User IDs.
participant_ids = ["2244994945", "1716450569358098432"]
# Set the text of the message to be sent.
text_message = "Hi, I am creating a new *group* conversation, and starting it with the this message."
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Create group conversation with DM
payload = {
"message": {"text": text_message},
"participant_ids": participant_ids,
"conversation_type": "Group"
}
response = client.direct_messages.create_conversation(body=payload)
print("Response code: 201")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/direct_messages/post_one_to_one_dm.py
================================================
"""
Post One-to-One Direct Message - X API v2
==========================================
Endpoint: POST https://api.x.com/2/dm_conversations/with/:participant_id/messages
Docs: https://developer.x.com/en/docs/twitter-api/direct-messages/manage/api-reference/post-dm-conversations-with-participant_id-messages
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["dm.read", "dm.write", "tweet.read", "users.read", "offline.access"]
# Who is this DM being sent to? Reference their User ID.
participant_id = "1716450569358098432"
# Set the text of the message to be sent.
text_message = "Hi, I am DMing you using the v2 DM one-to-one endpoint."
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Send one-to-one DM
payload = {"text": text_message}
response = client.direct_messages.create_by_participant_id(participant_id, body=payload)
print("Response code: 201")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/lists/add_member.py
================================================
"""
Add List Member - X API v2
==========================
Endpoint: POST https://api.x.com/2/lists/:id/members
Docs: https://developer.x.com/en/docs/twitter-api/lists/list-members/api-reference/post-lists-id-members
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "list.read", "list.write", "offline.access"]
# Be sure to replace your-list-id with your own list ID or one of an authenticated user
list_id = "your-list-id"
# Be sure to replace user-id-to-add with the user id you wish to add.
user_id = "user-id-to-add"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Add member to list
payload = {"user_id": user_id}
response = client.lists.add_member(list_id, body=payload)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/lists/create_list.py
================================================
"""
Create List - X API v2
======================
Endpoint: POST https://api.x.com/2/lists
Docs: https://developer.x.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-lists
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "list.read", "list.write", "offline.access"]
# Be sure to replace name-of-list with the name you wish to call the list.
# description and private keys are optional
payload = {
"name": "name-of-list",
"description": "description-of-list",
"private": False
}
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Create the list
response = client.lists.create(body=payload)
print("Response code: 201")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/lists/delete_list.py
================================================
"""
Delete List - X API v2
======================
Endpoint: DELETE https://api.x.com/2/lists/:id
Docs: https://developer.x.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "list.read", "list.write", "offline.access"]
# Be sure to replace your-list-id with the id of the list you wish to delete.
# The authenticated user must own the list in order to delete it.
list_id = "your-list-id"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Delete the list
response = client.lists.delete_list(list_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/lists/get_list_by_id.py
================================================
"""
List Lookup by ID - X API v2
=============================
Endpoint: GET https://api.x.com/2/lists/:id
Docs: https://developer.x.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
if not bearer_token:
raise ValueError("BEARER_TOKEN environment variable is not set")
client = Client(bearer_token=bearer_token)
# You can replace the ID given with the List ID you wish to lookup.
list_id = "list-id"
def main():
# List fields are adjustable. Options include:
# created_at, follower_count, member_count, private, description, owner_id
response = client.lists.get_by_id(
list_id,
list_fields=["created_at", "follower_count", "member_count", "owner_id", "description"]
)
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/lists/get_list_followers.py
================================================
"""
List Followers Lookup - X API v2
=================================
Endpoint: GET https://api.x.com/2/lists/:id/followers
Docs: https://developer.x.com/en/docs/twitter-api/lists/list-follows/api-reference/get-lists-id-followers
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
if not bearer_token:
raise ValueError("BEARER_TOKEN environment variable is not set")
client = Client(bearer_token=bearer_token)
# You can replace list-id with the List ID you wish to find followers of.
# Note: Private lists require OAuth 2.0 user context authentication.
list_id = "list-id"
def main():
# Get list followers with automatic pagination
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
all_users = []
for page in client.lists.get_followers(
list_id,
max_results=100,
user_fields=["created_at", "description", "verified"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_users.extend(page_data)
print(f"Fetched {len(page_data)} users (total: {len(all_users)})")
print(f"\nTotal Followers: {len(all_users)}")
print(json.dumps({"data": all_users[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/lists/get_list_members.py
================================================
"""
List Members Lookup - X API v2
==============================
Endpoint: GET https://api.x.com/2/lists/:id/members
Docs: https://developer.x.com/en/docs/twitter-api/lists/list-members/api-reference/get-lists-id-members
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# You can replace list-id with the List ID you wish to find members of.
list_id = "list-id"
def main():
# Get list members with automatic pagination
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
all_users = []
for page in client.lists.get_members(
list_id,
max_results=100,
user_fields=["created_at", "description", "verified"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_users.extend(page_data)
print(f"Fetched {len(page_data)} users (total: {len(all_users)})")
print(f"\nTotal Members: {len(all_users)}")
print(json.dumps({"data": all_users[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/lists/get_list_posts.py
================================================
"""
List Tweets - X API v2
======================
Endpoint: GET https://api.x.com/2/lists/:id/tweets
Docs: https://developer.x.com/en/docs/twitter-api/lists/list-tweets/api-reference/get-lists-id-tweets
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Be sure to replace list-id with any List ID
list_id = "list-id"
def main():
# Get list tweets with automatic pagination
# Tweet fields are adjustable.
# Options include:
# attachments, author_id, context_annotations,
# conversation_id, created_at, entities, geo, id,
# in_reply_to_user_id, lang, non_public_metrics, organic_metrics,
# possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets,
# source, text, and withheld
all_posts = []
for page in client.lists.get_posts(
list_id,
max_results=100,
tweet_fields=["lang", "author_id"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_posts.extend(page_data)
print(f"Fetched {len(page_data)} posts (total: {len(all_posts)})")
print(f"\nTotal Posts: {len(all_posts)}")
print(json.dumps({"data": all_posts[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/lists/remove_member.py
================================================
"""
Remove List Member - X API v2
==============================
Endpoint: DELETE https://api.x.com/2/lists/:id/members/:user_id
Docs: https://developer.x.com/en/docs/twitter-api/lists/list-members/api-reference/delete-lists-id-members-user_id
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "list.read", "list.write", "offline.access"]
# Be sure to replace your-list-id with your own list ID or one of an authenticated user
list_id = "your-list-id"
# Be sure to replace user-id-to-remove with the id of the user you wish to remove.
# You can find a user ID by using the user lookup endpoint
user_id = "user-id-to-remove"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Remove member from list
response = client.lists.remove_member(list_id, user_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/lists/update_list.py
================================================
"""
Update List - X API v2
======================
Endpoint: PUT https://api.x.com/2/lists/:id
Docs: https://developer.x.com/en/docs/twitter-api/lists/manage-lists/api-reference/put-lists-id
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "list.read", "list.write", "offline.access"]
# Be sure to replace update-name-of-list with the name you wish to call the list.
# name, description and private are all optional
payload = {
"name": "update-name-of-list",
"description": "update-description-of-list",
"private": False
}
# Be sure to replace your-list-id with the id of the list you wish to update.
# The authenticated user must own the list in order to update it.
list_id = "list-id"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Update the list
response = client.lists.update(list_id, body=payload)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/media/media_upload_v2.py
================================================
"""
Media Upload v2 (Video) - X API v2
===================================
Endpoint: POST https://api.x.com/2/media/upload
Docs: https://developer.x.com/en/docs/twitter-api/media/upload-media/api-reference
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
This example demonstrates uploading a video file using chunked uploads.
"""
import os
import sys
import time
import requests
from xdk.oauth2_auth import OAuth2PKCEAuth
MEDIA_ENDPOINT_URL = 'https://api.x.com/2/media/upload'
POST_TO_X_URL = 'https://api.x.com/2/tweets'
# Replace with path to file
VIDEO_FILENAME = 'REPLACE_ME'
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["media.write", "users.read", "tweet.read", "tweet.write", "offline.access"]
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access = tokens["access_token"]
headers = {
"Authorization": "Bearer {}".format(access),
"Content-Type": "application/json",
"User-Agent": "MediaUploadSampleCode",
}
class VideoPost(object):
def __init__(self, file_name):
# Defines video Post properties
self.video_filename = file_name
self.total_bytes = os.path.getsize(self.video_filename)
self.media_id = None
self.processing_info = None
def upload_init(self):
# Initializes Upload
print('INIT')
request_data = {
'command': 'INIT',
'media_type': 'video/mp4',
'total_bytes': self.total_bytes,
'media_category': 'tweet_video'
}
req = requests.post(url=MEDIA_ENDPOINT_URL, params=request_data, headers=headers)
print(req.status_code)
print(req.text)
media_id = req.json()['data']['id']
self.media_id = media_id
print('Media ID: %s' % str(media_id))
def upload_append(self):
segment_id = 0
bytes_sent = 0
with open(self.video_filename, 'rb') as file:
while bytes_sent < self.total_bytes:
chunk = file.read(4 * 1024 * 1024) # 4MB chunk size
print('APPEND')
files = {'media': ('chunk', chunk, 'application/octet-stream')}
data = {
'command': 'APPEND',
'media_id': self.media_id,
'segment_index': segment_id
}
headers = {
"Authorization": f"Bearer {access}",
"User-Agent": "MediaUploadSampleCode",
}
req = requests.post(url=MEDIA_ENDPOINT_URL, data=data, files=files, headers=headers)
if req.status_code < 200 or req.status_code > 299:
print(req.status_code)
print(req.text)
sys.exit(0)
segment_id += 1
bytes_sent = file.tell()
print(f'{bytes_sent} of {self.total_bytes} bytes uploaded')
print('Upload chunks complete.')
def upload_finalize(self):
# Finalizes uploads and starts video processing
print('FINALIZE')
request_data = {
'command': 'FINALIZE',
'media_id': self.media_id
}
req = requests.post(url=MEDIA_ENDPOINT_URL, params=request_data, headers=headers)
print(req.json())
self.processing_info = req.json()['data'].get('processing_info', None)
self.check_status()
def check_status(self):
# Checks video processing status
if self.processing_info is None:
return
state = self.processing_info['state']
print('Media processing status is %s ' % state)
if state == u'succeeded':
return
if state == u'failed':
sys.exit(0)
check_after_secs = self.processing_info['check_after_secs']
print('Checking after %s seconds' % str(check_after_secs))
time.sleep(check_after_secs)
print('STATUS')
request_params = {
'command': 'STATUS',
'media_id': self.media_id
}
req = requests.get(url=MEDIA_ENDPOINT_URL, params=request_params, headers=headers)
self.processing_info = req.json()['data'].get('processing_info', None)
self.check_status()
def post(self):
# Publishes Post with attached video
payload = {
'text': 'I just uploaded a video with the media upload v2 @XDevelopers API.',
'media': {
'media_ids': [self.media_id]
}
}
req = requests.post(url=POST_TO_X_URL, json=payload, headers=headers)
print(req.json())
if __name__ == '__main__':
videoPost = VideoPost(VIDEO_FILENAME)
videoPost.upload_init()
videoPost.upload_append()
videoPost.upload_finalize()
videoPost.post()
================================================
FILE: python/media/upload.py
================================================
"""
Media Upload - X API v2
=======================
Endpoint: POST https://upload.x.com/1.1/media/upload.json
Docs: https://developer.x.com/en/docs/twitter-api/media/upload-media/api-reference
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
This example demonstrates uploading an image to attach to a post.
"""
import os
import json
import base64
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "tweet.write", "users.read", "offline.access"]
# Path to the media file you want to upload
media_path = "path/to/your/image.jpg"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Read and upload the media file
with open(media_path, "rb") as media_file:
media_data = base64.b64encode(media_file.read()).decode("utf-8")
payload = {"media_data": media_data}
response = client.media.upload_media(body=payload)
print("Response code: 200")
# Get the media_id to use when creating a post
media_id = response.data["media_id_string"]
print("Media ID: {}".format(media_id))
print(json.dumps(response.data, indent=4, sort_keys=True))
# You can now use this media_id when creating a post:
# payload = {"text": "My post with media!", "media": {"media_ids": [media_id]}}
if __name__ == "__main__":
main()
================================================
FILE: python/posts/create_post.py
================================================
"""
Create Tweet - X API v2
=======================
Endpoint: POST https://api.x.com/2/tweets
Docs: https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "tweet.write", "users.read", "offline.access"]
# Be sure to replace the text with the text you wish to Tweet.
# You can also add parameters to post polls, quote Tweets, Tweet with reply settings, and Tweet to Super Followers in addition to other features.
payload = {"text": "Hello world!"}
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Create the tweet
response = client.posts.create(body=payload)
print("Response code: 201")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/posts/delete_post.py
================================================
"""
Delete Tweet - X API v2
=======================
Endpoint: DELETE https://api.x.com/2/tweets/:id
Docs: https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/delete-tweets-id
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "tweet.write", "users.read", "offline.access"]
# Be sure to replace tweet-id-to-delete with the id of the Tweet you wish to delete.
# The authenticated user must own the Tweet in order to delete it.
post_id = "1997118644242014409"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Delete the tweet
response = client.posts.delete(post_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/posts/get_liking_users.py
================================================
"""
Liking Users - X API v2
======================
Endpoint: GET https://api.x.com/2/tweets/:id/liking_users
Docs: https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/get-tweets-id-liking_users
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
from requests.exceptions import HTTPError
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "like.read", "offline.access"]
# You can replace the ID given with the Post ID you wish to get liking users for.
# You can find an ID by using the Post lookup endpoint
post_id = "post-id"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get liking users with automatic pagination
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
all_users = []
for page in client.posts.get_liking_users(
post_id,
max_results=100,
user_fields=["created_at", "description"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_users.extend(page_data)
print(f"Fetched {len(page_data)} users (total: {len(all_users)})")
print(f"\nTotal Users: {len(all_users)}")
print(json.dumps({"data": all_users[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/posts/get_post_by_id.py
================================================
"""
Single Post Lookup - X API v2
=============================
Endpoint: GET https://api.x.com/2/tweets/:id
Docs: https://developer.x.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets-id
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with the Post ID you want to look up
post_id = "post-id"
def main():
# Post fields are adjustable. Options include:
# attachments, author_id, context_annotations, conversation_id,
# created_at, entities, geo, id, in_reply_to_user_id, lang,
# non_public_metrics, organic_metrics, possibly_sensitive,
# promoted_metrics, public_metrics, referenced_tweets,
# source, text, and withheld
response = client.posts.get_by_id(
post_id,
tweet_fields=["created_at", "author_id", "lang", "source", "public_metrics", "entities"]
)
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/posts/get_post_counts_all.py
================================================
"""
Full-Archive Post Counts - X API v2
===================================
Endpoint: GET https://api.x.com/2/tweets/counts/all
Docs: https://developer.x.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-all
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
Note: Requires Academic Research access. Returns counts from the entire archive.
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
query = "from:XDevelopers"
def main():
# Get counts with automatic pagination
# Optional: You can add start_time parameter to limit the date range
# Example: start_time="2021-01-01T00:00:00Z"
all_counts = []
for page in client.posts.get_counts_all(
query=query,
granularity="day"
# start_time="2021-01-01T00:00:00Z" # Optional: uncomment to add date range
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_counts.extend(page_data)
print(f"Fetched {len(page_data)} count buckets (total: {len(all_counts)})")
print(f"\nTotal Count Buckets: {len(all_counts)}")
print(json.dumps({"data": all_counts}, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/posts/get_post_counts_recent.py
================================================
"""
Recent Post Counts - X API v2
=============================
Endpoint: GET https://api.x.com/2/tweets/counts/recent
Docs: https://developer.x.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-recent
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
Note: Returns count of posts from the last 7 days matching your query.
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
query = "from:XDevelopers"
def main():
# Get counts with automatic pagination
all_counts = []
for page in client.posts.get_counts_recent(
query=query,
granularity="day"
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_counts.extend(page_data)
print(f"Fetched {len(page_data)} count buckets (total: {len(all_counts)})")
print(f"\nTotal Count Buckets: {len(all_counts)}")
print(json.dumps({"data": all_counts}, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/posts/get_posts_by_ids.py
================================================
"""
Post Lookup - X API v2
======================
Endpoint: GET https://api.x.com/2/tweets
Docs: https://developer.x.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Post IDs to look up (comma-separated list, up to 100)
# You can adjust ids to include a single Post or add up to 100 comma-separated IDs
post_ids = ["post-id-1", "post-id-2"]
def main():
# Post fields are adjustable. Options include:
# attachments, author_id, context_annotations, conversation_id,
# created_at, entities, geo, id, in_reply_to_user_id, lang,
# non_public_metrics, organic_metrics, possibly_sensitive,
# promoted_metrics, public_metrics, referenced_tweets,
# source, text, and withheld
response = client.posts.get_by_ids(
ids=post_ids,
tweet_fields=["created_at", "author_id", "lang", "source", "public_metrics", "context_annotations", "entities"]
)
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/posts/get_quoted_posts.py
================================================
"""
Quote Tweets Lookup - X API v2
==============================
Endpoint: GET https://api.x.com/2/tweets/:id/quote_tweets
Docs: https://developer.x.com/en/docs/twitter-api/tweets/quote-tweets/api-reference/get-tweets-id-quote_tweets
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with the post ID you want to get quotes for
post_id = "1409931481552543749"
def main():
# Get quote tweets with automatic pagination
# Tweet fields are adjustable.
# Options include:
# attachments, author_id, context_annotations,
# conversation_id, created_at, entities, geo, id,
# in_reply_to_user_id, lang, non_public_metrics, organic_metrics,
# possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets,
# source, text, and withheld
all_posts = []
for page in client.posts.get_quoted(
post_id,
max_results=100,
tweet_fields=["created_at"]
):
all_posts.extend(page.data)
print(f"Fetched {len(page.data)} posts (total: {len(all_posts)})")
print(f"\nTotal Quote Tweets: {len(all_posts)}")
print(json.dumps({"data": all_posts[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/posts/get_reposted_by.py
================================================
"""
Retweeted By (Users who reposted) - X API v2
============================================
Endpoint: GET https://api.x.com/2/tweets/:id/retweeted_by
Docs: https://developer.x.com/en/docs/twitter-api/tweets/retweets/api-reference/get-tweets-id-retweeted_by
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# You can replace the ID given with the Post ID you wish to lookup reposting users for
# You can find an ID by using the Post lookup endpoint
post_id = "post-id"
def main():
# Get reposted by users with automatic pagination
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
all_users = []
for page in client.posts.get_reposted_by(
post_id,
max_results=100,
user_fields=["created_at", "description"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_users.extend(page_data)
print(f"Fetched {len(page_data)} users (total: {len(all_users)})")
print(f"\nTotal Users: {len(all_users)}")
print(json.dumps({"data": all_users[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/posts/hide_reply.py
================================================
"""
Hide Reply - X API v2
=====================
Endpoint: PUT https://api.x.com/2/tweets/:id/hidden
Docs: https://developer.x.com/en/docs/twitter-api/tweets/hide-replies/api-reference/put-tweets-id-hidden
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
Note: You can only hide or unhide replies to conversations you authored.
Pass hidden=True to hide a reply, or hidden=False to unhide one.
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "tweet.write", "users.read", "offline.access"]
# Replace with the ID of the reply you wish to hide.
# You can only hide replies to conversations you authored.
tweet_id = "reply-tweet-id-to-hide"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Hide the reply
# Set hidden=False to unhide a previously hidden reply
response = client.posts.hide_reply(tweet_id, hidden=True)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/posts/search_all.py
================================================
"""
Full-Archive Search - X API v2
==============================
Endpoint: GET https://api.x.com/2/tweets/search/all
Docs: https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-all
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
Note: Requires Academic Research access. Returns posts from the entire archive.
This example demonstrates automatic pagination using the iterate() method
to fetch all pages of results.
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
query = '(from:xdevelopers -is:retweet) OR #xdevelopers'
def main():
# Search with automatic pagination
all_posts = []
for page in client.posts.search_all(
query=query,
max_results=100, # Per page
tweet_fields=["author_id", "created_at"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_posts.extend(page_data)
print(f"Fetched {len(page_data)} Posts (total: {len(all_posts)})")
print(f"\nTotal Posts: {len(all_posts)}")
print(json.dumps({"data": all_posts[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/posts/search_recent.py
================================================
"""
Recent Search - X API v2
========================
Endpoint: GET https://api.x.com/2/tweets/search/recent
Docs: https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
Note: Returns posts from the last 7 days.
This example demonstrates automatic pagination using the iterate() method
to fetch all pages of results.
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
query = '(from:XDevelopers -is:retweet) OR #XDevelopers'
def main():
# Search with automatic pagination
all_posts = []
for page in client.posts.search_recent(
query=query,
max_results=100, # Per page
tweet_fields=["author_id", "created_at"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_posts.extend(page_data)
print(f"Fetched {len(page_data)} Posts (total: {len(all_posts)})")
print(f"\nTotal Posts: {len(all_posts)}")
print(json.dumps({"data": all_posts[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/requirements.txt
================================================
xdk>=0.4.5
flask>=3.0.0
waitress>=3.0.0
================================================
FILE: python/spaces/get_spaces_by_ids.py
================================================
"""
Spaces Lookup - X API v2
========================
Endpoint: GET https://api.x.com/2/spaces
Docs: https://developer.x.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Space IDs to look up (list)
# You can replace the IDs with actual Space IDs you want to look up
space_ids = ["space-id-1", "space-id-2"]
def main():
# Optional params: host_ids, conversation_controls, created_at, creator_id, id, invited_user_ids,
# is_ticketed, lang, media_key, participants, scheduled_start, speaker_ids, started_at, state, title, updated_at
response = client.spaces.get_by_ids(
ids=space_ids,
space_fields=["title", "created_at"],
expansions=["creator_id"]
)
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/spaces/search_spaces.py
================================================
"""
Search Spaces - X API v2
========================
Endpoint: GET https://api.x.com/2/spaces/search
Docs: https://developer.x.com/en/docs/twitter-api/spaces/search/api-reference/get-spaces-search
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace this value with your search term
search_term = 'NBA'
def main():
# Optional params: host_ids, conversation_controls, created_at, creator_id, id, invited_user_ids,
# is_ticketed, lang, media_key, participants, scheduled_start, speaker_ids, started_at, state, title, updated_at
response = client.spaces.search(
query=search_term,
space_fields=["title", "created_at"],
expansions=["creator_id"]
)
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/streams/stream_posts_filtered.py
================================================
"""
Filtered Stream - X API v2
==========================
Endpoint: GET https://api.x.com/2/tweets/search/stream
Docs: https://developer.x.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
Note: Streams posts matching your filter rules in real-time.
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
def get_rules():
response = client.stream.get_rules()
# Access data attribute safely
rules_data = getattr(response, 'data', None)
if rules_data:
print(json.dumps(rules_data, indent=4, sort_keys=True))
return rules_data
def delete_all_rules(rules):
if rules is None or not rules:
return None
ids = [rule["id"] for rule in rules]
payload = {"delete": {"ids": ids}}
response = client.stream.update_rules(body=payload)
# Access data attribute safely
response_data = getattr(response, 'data', None)
if response_data:
print(json.dumps(response_data, indent=4, sort_keys=True))
def set_rules():
# You can adjust the rules if needed
sample_rules = [
{"value": "dog has:images", "tag": "dog pictures"},
{"value": "cat has:images -grumpy", "tag": "cat pictures"},
]
payload = {"add": sample_rules}
response = client.stream.update_rules(body=payload)
# Access data attribute safely
response_data = getattr(response, 'data', None)
if response_data:
print(json.dumps(response_data, indent=4, sort_keys=True))
def get_stream():
# Stream posts matching the filter rules in real-time
# The posts() method is the filtered stream
try:
for post in client.stream.posts():
# Access data attribute safely
post_data = getattr(post, 'data', None)
if post_data:
print(json.dumps(post_data, indent=4, sort_keys=True))
except Exception as e:
print(f"Error streaming posts: {e}")
print("Note: This could be a temporary API issue (503 Service Unavailable)")
print("or the stream endpoint may be experiencing issues.")
raise
def main():
rules = get_rules()
delete_all_rules(rules)
set_rules()
get_stream()
if __name__ == "__main__":
main()
================================================
FILE: python/streams/stream_posts_sample.py
================================================
"""
Sampled Stream (1% Volume) - X API v2
=====================================
Endpoint: GET https://api.x.com/2/tweets/sample/stream
Docs: https://developer.x.com/en/docs/twitter-api/tweets/volume-streams/api-reference/get-tweets-sample-stream
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
Note: Returns approximately 1% of all public posts in real-time.
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
def main():
# Stream posts in real-time
for post in client.stream.posts_sample():
print(json.dumps(post.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/usage/get_usage.py
================================================
"""
Usage Posts - X API v2
======================
Endpoint: GET https://api.x.com/2/usage/tweets
Docs: https://developer.x.com/en/docs/twitter-api/usage/api-reference/get-usage-tweets
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
Returns the number of posts read from the API.
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
def main():
# Get usage statistics for tweets
# days: Number of days to retrieve usage for (default: 7)
# usage_fields: Fields to include in the response (optional)
response = client.usage.get(days=7)
# Access data attribute safely
response_data = getattr(response, 'data', None)
if response_data:
print(json.dumps(response_data, indent=4, sort_keys=True))
else:
print(json.dumps(response, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/block/get_blocking.py
================================================
"""
Blocked Users Lookup - X API v2
===============================
Endpoint: GET https://api.x.com/2/users/:id/blocking
Docs: https://developer.x.com/en/docs/twitter-api/users/blocks/api-reference/get-users-blocking
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
from requests.exceptions import HTTPError
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "offline.access", "block.read"]
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get the authenticated user's ID
me_response = client.users.get_me()
user_id = me_response.data["id"]
# Step 7: Get blocked users with automatic pagination
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
all_users = []
try:
for page in client.users.get_blocking(
user_id,
max_results=100,
user_fields=["created_at", "description"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_users.extend(page_data)
print(f"Fetched {len(page_data)} users (total: {len(all_users)})")
print(f"\nTotal Blocked Users: {len(all_users)}")
print(json.dumps({"data": all_users[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
except HTTPError as e:
print(f"Error occurred: {e}")
if hasattr(e.response, 'json'):
try:
error_data = e.response.json()
if 'errors' in error_data:
print("Detailed errors:")
print(json.dumps(error_data['errors'], indent=2))
except:
pass
raise
if __name__ == "__main__":
main()
================================================
FILE: python/users/bookmark/create_bookmark.py
================================================
"""
Create Bookmark - X API v2
==========================
Endpoint: POST https://api.x.com/2/users/:id/bookmarks
Docs: https://developer.x.com/en/docs/twitter-api/tweets/bookmarks/api-reference/post-users-id-bookmarks
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "bookmark.write", "offline.access"]
# Replace with a Post ID you want to Bookmark
post_id = "post-id-to-bookmark"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get authenticated user ID
me_response = client.users.get_me()
user_id = me_response.data["id"]
# Step 7: Create bookmark
payload = {"tweet_id": post_id}
response = client.users.create_bookmark(user_id, body=payload)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/bookmark/delete_bookmark.py
================================================
"""
Delete Bookmark - X API v2
==========================
Endpoint: DELETE https://api.x.com/2/users/:id/bookmarks/:tweet_id
Docs: https://developer.x.com/en/docs/twitter-api/tweets/bookmarks/api-reference/delete-users-id-bookmarks-tweet_id
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "bookmark.write", "offline.access"]
# Replace with a Post ID you want to remove Bookmark of
post_id = "post-id-to-unbookmark"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get authenticated user ID
me_response = client.users.get_me()
user_id = me_response.data["id"]
# Step 7: Delete bookmark
response = client.users.delete_bookmark(user_id, post_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/bookmark/get_bookmarks.py
================================================
"""
Bookmarks Lookup - X API v2
===========================
Endpoint: GET https://api.x.com/2/users/:id/bookmarks
Docs: https://developer.x.com/en/docs/twitter-api/bookmarks/api-reference/get-users-id-bookmarks
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["bookmark.read", "tweet.read", "users.read", "offline.access"]
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get authenticated user ID
user_me = client.users.get_me()
user_id = user_me.data["id"]
# Step 7: Get bookmarks with automatic pagination
all_bookmarks = []
for page in client.users.get_bookmarks(
user_id,
max_results=100,
tweetfields=["created_at"]
):
all_bookmarks.extend(page.data)
print(f"Fetched {len(page.data)} bookmarks (total: {len(all_bookmarks)})")
print(f"\nTotal Bookmarks: {len(all_bookmarks)}")
print(json.dumps({"data": all_bookmarks[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/users/follow/follow_user.py
================================================
"""
Follow User - X API v2
======================
Endpoint: POST https://api.x.com/2/users/:id/following
Docs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/post-users-id-following
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "follows.write", "offline.access"]
# Be sure to replace user-id-to-follow with the user id you wish to follow.
# You can find a user ID by using the user lookup endpoint
target_user_id = "user-id-to-follow"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get the authenticated user's ID
me_response = client.users.get_me()
user_id = me_response.data["id"]
# Step 7: Follow the user
payload = {"target_user_id": target_user_id}
response = client.users.follow_user(user_id, body=payload)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/follow/get_followers.py
================================================
"""
User Followers Lookup - X API v2
================================
Endpoint: GET https://api.x.com/2/users/:id/followers
Docs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with the user ID you want to get followers for
user_id = "2244994945"
def main():
# Get followers with automatic pagination
all_users = []
for page in client.users.get_followers(
user_id,
max_results=100,
user_fields=["created_at"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_users.extend(page_data)
print(f"Fetched {len(page_data)} users (total: {len(all_users)})")
print(f"\nTotal Followers: {len(all_users)}")
print(json.dumps({"data": all_users[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/users/follow/get_following.py
================================================
"""
User Following Lookup - X API v2
================================
Endpoint: GET https://api.x.com/2/users/:id/following
Docs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with the user ID you want to get following for
user_id = "2244994945"
def main():
# Get following with automatic pagination
all_users = []
for page in client.users.get_following(
user_id,
max_results=100,
user_fields=["created_at"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_users.extend(page_data)
print(f"Fetched {len(page_data)} users (total: {len(all_users)})")
print(f"\nTotal Following: {len(all_users)}")
print(json.dumps({"data": all_users[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/users/follow/unfollow_user.py
================================================
"""
Unfollow User - X API v2
========================
Endpoint: DELETE https://api.x.com/2/users/:source_user_id/following/:target_user_id
Docs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/delete-users-source_user_id-following
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "follows.write", "offline.access"]
# Be sure to replace user-id-to-unfollow with the id of the user you wish to unfollow.
# You can find a user ID by using the user lookup endpoint
target_user_id = "user-id-to-unfollow"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get the authenticated user's ID
me_response = client.users.get_me()
user_id = me_response.data["id"]
# Step 7: Unfollow the user
response = client.users.unfollow_user(user_id, target_user_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/get_users_by_usernames.py
================================================
"""
User Lookup - X API v2
======================
Endpoint: GET https://api.x.com/2/users/by
Docs: https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Specify the usernames that you want to lookup (list, up to 100)
usernames = ["XDevelopers", "API"]
def main():
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
response = client.users.get_by_usernames(
usernames=usernames,
user_fields=["description", "created_at"]
)
# Access data attribute safely
response_data = getattr(response, 'data', None)
if response_data:
print(json.dumps(response_data, indent=4, sort_keys=True))
else:
print(json.dumps(response, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/get_users_by_usernames_user_context.py
================================================
"""
User Lookup (User Context) - X API v2
=====================================
Endpoint: GET https://api.x.com/2/users/by
Docs: https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "offline.access"]
# Specify the usernames that you want to lookup (list, up to 100)
usernames = ["XDevelopers", "API"]
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get users
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
response = client.users.get_by_usernames(
usernames=usernames,
user_fields=["created_at", "description"]
)
# Access data attribute safely
response_data = getattr(response, 'data', None)
if response_data:
print(json.dumps(response_data, indent=4, sort_keys=True))
else:
print(json.dumps(response, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/get_users_me.py
================================================
"""
Authenticated User Lookup (Me) - X API v2
=========================================
Endpoint: GET https://api.x.com/2/users/me
Docs: https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "offline.access"]
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get authenticated user info
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
response = client.users.get_me(
user_fields=["created_at", "description"]
)
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/like/get_liked_posts.py
================================================
"""
Liked Tweets - X API v2
======================
Endpoint: GET https://api.x.com/2/users/:id/liked_tweets
Docs: https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/get-users-id-liked_tweets
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "like.read", "offline.access"]
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get the authenticated user's ID
user_me = client.users.get_me()
user_id = user_me.data["id"]
# Step 7: Get liked tweets with automatic pagination
# Tweet fields are adjustable.
# Options include:
# attachments, author_id, context_annotations,
# conversation_id, created_at, entities, geo, id,
# in_reply_to_user_id, lang, non_public_metrics, organic_metrics,
# possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets,
# source, text, and withheld
all_posts = []
for page in client.users.get_liked_posts(
user_id,
max_results=100,
tweet_fields=["lang", "author_id"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_posts.extend(page_data)
print(f"Fetched {len(page_data)} posts (total: {len(all_posts)})")
print(f"\nTotal Liked Tweets: {len(all_posts)}")
print(json.dumps({"data": all_posts[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/users/like/like_post.py
================================================
"""
Like a Tweet - X API v2
======================
Endpoint: POST https://api.x.com/2/users/:id/likes
Docs: https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/post-users-id-likes
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "tweet.write", "users.read", "offline.access", "like.write"]
# You can replace Tweet ID given with the Tweet ID you wish to like.
# You can find a Tweet ID by using the Tweet lookup endpoint
post_id = "post-id"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get the authenticated user's ID
user_me = client.users.get_me()
user_id = user_me.data["id"]
# Step 7: Like the tweet
payload = {"tweet_id": post_id}
response = client.users.like_post(user_id, body=payload)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/like/unlike_post.py
================================================
"""
Unlike a Tweet - X API v2
========================
Endpoint: DELETE https://api.x.com/2/users/:id/likes/:tweet_id
Docs: https://developer.x.com/en/docs/twitter-api/tweets/likes/api-reference/delete-users-id-likes-tweet_id
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "tweet.write", "users.read", "offline.access", "like.write"]
# You can replace Tweet ID given with the Tweet ID you wish to unlike.
# You can find a Tweet ID by using the Tweet lookup endpoint
post_id = "post-id"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get the authenticated user's ID
user_me = client.users.get_me()
user_id = user_me.data["id"]
# Step 7: Unlike the tweet
response = client.users.unlike_post(user_id, tweet_id=post_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/lists/follow_list.py
================================================
"""
Follow List - X API v2
=====================
Endpoint: POST https://api.x.com/2/users/:id/followed_lists
Docs: https://developer.x.com/en/docs/twitter-api/lists/list-follows/api-reference/post-users-id-followed_lists
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "list.read", "list.write", "offline.access"]
# Be sure to replace your-user-id with your own user ID or one of an authenticated user
# You can find a user ID by using the user lookup endpoint
user_id = "your-user-id"
# Be sure to replace list-id-to-follow with the list id you wish to follow.
list_id = "list-id-to-follow"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Follow the list
payload = {"list_id": list_id}
response = client.users.follow_list(user_id, body=payload)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/lists/get_followed_lists.py
================================================
"""
User Followed Lists Lookup - X API v2
======================================
Endpoint: GET https://api.x.com/2/users/:id/followed_lists
Docs: https://developer.x.com/en/docs/twitter-api/lists/list-follows/api-reference/get-users-id-followed_lists
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# You can replace the user-id with any valid User ID you wish to find what Lists they are following.
user_id = "user-id"
def main():
# Get user followed lists with automatic pagination
# List fields are adjustable, options include:
# created_at, description, owner_id,
# private, follower_count, member_count,
all_lists = []
for page in client.users.get_followed_lists(
user_id,
max_results=100,
list_fields=["created_at", "follower_count"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_lists.extend(page_data)
print(f"Fetched {len(page_data)} lists (total: {len(all_lists)})")
print(f"\nTotal Followed Lists: {len(all_lists)}")
print(json.dumps({"data": all_lists[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/users/lists/get_list_memberships.py
================================================
"""
User List Memberships Lookup - X API v2
=======================================
Endpoint: GET https://api.x.com/2/users/:id/list_memberships
Docs: https://developer.x.com/en/docs/twitter-api/lists/list-members/api-reference/get-users-id-list_memberships
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# You can replace the user-id with any valid User ID you wish to find what Lists they are members of.
user_id = "user-id"
def main():
# Get user list memberships with automatic pagination
# List fields are adjustable, options include:
# created_at, description, owner_id,
# private, follower_count, member_count,
all_lists = []
for page in client.users.get_list_memberships(
user_id,
max_results=100,
list_fields=["created_at", "follower_count"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_lists.extend(page_data)
print(f"Fetched {len(page_data)} lists (total: {len(all_lists)})")
print(f"\nTotal List Memberships: {len(all_lists)}")
print(json.dumps({"data": all_lists[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/users/lists/get_owned_lists.py
================================================
"""
User Owned Lists Lookup - X API v2
===================================
Endpoint: GET https://api.x.com/2/users/:id/owned_lists
Docs: https://developer.x.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-users-id-owned_lists
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# You can replace user-id with any valid User ID to see if they own any Lists.
user_id = "user-id"
def main():
# Get user owned lists with automatic pagination
# List fields are adjustable, options include:
# created_at, description, owner_id,
# private, follower_count, member_count,
all_lists = []
for page in client.users.get_owned_lists(
user_id,
max_results=100,
list_fields=["created_at", "follower_count"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_lists.extend(page_data)
print(f"Fetched {len(page_data)} lists (total: {len(all_lists)})")
print(f"\nTotal Owned Lists: {len(all_lists)}")
print(json.dumps({"data": all_lists[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/users/lists/get_pinned_lists.py
================================================
"""
Pinned Lists Lookup - X API v2
==============================
Endpoint: GET https://api.x.com/2/users/:id/pinned_lists
Docs: https://developer.x.com/en/docs/twitter-api/lists/pinned-lists/api-reference/get-users-id-pinned_lists
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "list.read", "offline.access"]
# Be sure to replace your-user-id with your own user ID or one of an authenticated user
# You can find a user ID by using the user lookup endpoint
user_id = "your-user-id"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get pinned lists
# List fields are adjustable, options include:
# created_at, description, owner_id,
# private, follower_count, member_count,
response = client.users.get_pinned_lists(
user_id,
list_fields=["created_at", "description", "private"]
)
# Access data attribute (model uses extra='allow' so data should be available)
response_data = getattr(response, 'data', None)
if response_data is None:
# Try accessing via model_dump if data attribute doesn't exist
response_dict = response.model_dump() if hasattr(response, 'model_dump') else {}
response_data = response_dict.get('data', response_dict)
print(f"Total Pinned Lists: {len(response_data) if isinstance(response_data, list) else 1}")
print(json.dumps(response_data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/lists/pin_list.py
================================================
"""
Pin List - X API v2
==================
Endpoint: POST https://api.x.com/2/users/:id/pinned_lists
Docs: https://developer.x.com/en/docs/twitter-api/lists/pinned-lists/api-reference/post-users-id-pinned_lists
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "list.read", "list.write", "offline.access"]
# Be sure to replace your-user-id with your own user ID or one of an authenticated user
# You can find a user ID by using the user lookup endpoint
user_id = "your-user-id"
# Be sure to replace list-id-to-pin with the list id you wish to pin.
list_id = "list-id-to-pin"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Pin the list
payload = {"list_id": list_id}
response = client.users.pin_list(user_id, body=payload)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/lists/unfollow_list.py
================================================
"""
Unfollow List - X API v2
========================
Endpoint: DELETE https://api.x.com/2/users/:id/followed_lists/:list_id
Docs: https://developer.x.com/en/docs/twitter-api/lists/list-follows/api-reference/delete-users-id-followed_lists-list_id
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "list.read", "list.write", "offline.access"]
# Be sure to replace your-user-id with your own user ID or one of an authenticated user
# You can find a user ID by using the user lookup endpoint
user_id = "your-user-id"
# Be sure to replace list-id-to-unfollow with the id of the list you wish to unfollow.
list_id = "list-id-to-unfollow"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Unfollow the list
response = client.users.unfollow_list(user_id, list_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/lists/unpin_list.py
================================================
"""
Unpin List - X API v2
=====================
Endpoint: DELETE https://api.x.com/2/users/:id/pinned_lists/:list_id
Docs: https://developer.x.com/en/docs/twitter-api/lists/pinned-lists/api-reference/delete-users-id-pinned_lists-list_id
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "list.read", "list.write", "offline.access"]
# Be sure to replace your-user-id with your own user ID or one of an authenticated user
# You can find a user ID by using the user lookup endpoint
user_id = "your-user-id"
# Be sure to replace list-id-to-unpin with the id of the list you wish to unpin.
list_id = "list-id-to-unpin"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Unpin the list
response = client.users.unpin_list(user_id, list_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/mute/get_muting.py
================================================
"""
Muted Users Lookup - X API v2
=============================
Endpoint: GET https://api.x.com/2/users/:id/muting
Docs: https://developer.x.com/en/docs/twitter-api/users/mutes/api-reference/get-users-muting
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
from requests.exceptions import HTTPError
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "offline.access", "mute.read"]
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get the authenticated user's ID
me_response = client.users.get_me()
user_id = me_response.data["id"]
# Step 7: Get muted users with automatic pagination
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
all_users = []
try:
for page in client.users.get_muting(
user_id,
max_results=100,
user_fields=["created_at", "description"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_users.extend(page_data)
print(f"Fetched {len(page_data)} users (total: {len(all_users)})")
print(f"\nTotal Muted Users: {len(all_users)}")
print(json.dumps({"data": all_users[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
except HTTPError as e:
print(f"Error occurred: {e}")
if hasattr(e.response, 'json'):
try:
error_data = e.response.json()
if 'errors' in error_data:
print("Detailed errors:")
print(json.dumps(error_data['errors'], indent=2))
except:
pass
raise
if __name__ == "__main__":
main()
================================================
FILE: python/users/mute/mute_user.py
================================================
"""
Mute User - X API v2
====================
Endpoint: POST https://api.x.com/2/users/:id/muting
Docs: https://developer.x.com/en/docs/twitter-api/users/mutes/api-reference/post-users-user_id-muting
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "tweet.write", "offline.access", "mute.write"]
# Be sure to replace your-user-id with your own user ID or one of an authenticated user
# You can find a user ID by using the user lookup endpoint
user_id = "your-user-id"
# Be sure to replace id-to-mute with the user id you wish to mute.
target_user_id = "id-to-mute"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Mute the user
payload = {"target_user_id": target_user_id}
response = client.users.mute_user(user_id, body=payload)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/mute/unmute_user.py
================================================
"""
Unmute User - X API v2
======================
Endpoint: DELETE https://api.x.com/2/users/:source_user_id/muting/:target_user_id
Docs: https://developer.x.com/en/docs/twitter-api/users/mutes/api-reference/delete-users-user_id-muting
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "tweet.write", "offline.access", "mute.write"]
# Be sure to replace your-user-id with your own user ID or one of an authenticated user
# You can find a user ID by using the user lookup endpoint
user_id = "your-user-id"
# Be sure to replace id-to-unmute with the id of the user you wish to unmute.
# You can find a user ID by using the user lookup endpoint
target_user_id = "id-to-unmute"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Unmute the user
response = client.users.unmute_user(user_id, target_user_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/repost/get_reposts_of_me.py
================================================
"""
Reposts of Me - X API v2
=========================
Endpoint: GET https://api.x.com/2/users/reposts_of_me
Docs: https://docs.x.com/x-api/users/get-reposts-of-me
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
Note: Returns posts from the authenticated user's timeline that have been reposted.
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "offline.access"]
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get the authenticated user's posts that have been reposted
# Post fields are adjustable. Options include:
# attachments, author_id, context_annotations, conversation_id,
# created_at, entities, geo, id, in_reply_to_user_id, lang,
# non_public_metrics, organic_metrics, possibly_sensitive,
# promoted_metrics, public_metrics, referenced_tweets,
# source, text, and withheld
all_posts = []
for page in client.users.get_reposts_of_me(
max_results=100,
tweet_fields=["created_at", "public_metrics"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_posts.extend(page_data)
print(f"Fetched {len(page_data)} posts (total: {len(all_posts)})")
print(f"\nTotal Reposted Posts: {len(all_posts)}")
print(json.dumps({"data": all_posts[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/users/repost/repost_post.py
================================================
"""
Retweet (Repost) - X API v2
===========================
Endpoint: POST https://api.x.com/2/users/:id/retweets
Docs: https://developer.x.com/en/docs/twitter-api/tweets/retweets/api-reference/post-users-id-retweets
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "tweet.write", "users.read", "offline.access"]
# You can replace the given Tweet ID with the Tweet ID you want to Retweet
# You can find a Tweet ID by using the Tweet lookup endpoint
post_id = "post-id"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get the authenticated user's ID
user_me = client.users.get_me()
user_id = user_me.data["id"]
# Step 7: Retweet the tweet
payload = {"tweet_id": post_id}
response = client.users.repost_post(user_id, body=payload)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/repost/unrepost_post.py
================================================
"""
Undo Retweet (Unrepost) - X API v2
==================================
Endpoint: DELETE https://api.x.com/2/users/:id/retweets/:source_tweet_id
Docs: https://developer.x.com/en/docs/twitter-api/tweets/retweets/api-reference/delete-users-id-retweets-tweet_id
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "tweet.write", "users.read", "offline.access"]
# You can replace the given Tweet ID with the Tweet ID you want to undo retweet for
# You can find a Tweet ID by using the Tweet lookup endpoint
source_post_id = "post-id"
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get the authenticated user's ID
user_me = client.users.get_me()
user_id = user_me.data["id"]
# Step 7: Undo retweet
response = client.users.unrepost_post(user_id, source_tweet_id=source_post_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/users/timeline/get_home_timeline.py
================================================
"""
Reverse Chronological Home Timeline - X API v2
==============================================
Endpoint: GET https://api.x.com/2/users/:id/timelines/reverse_chronological
Docs: https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-reverse-chronological-timeline
Authentication: OAuth 2.0 (User Context)
Required env vars: CLIENT_ID, CLIENT_SECRET
"""
import os
import json
from xdk import Client
from xdk.oauth2_auth import OAuth2PKCEAuth
# The code below sets the client ID and client secret from your environment variables
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CLIENT_ID='YOUR-CLIENT-ID'
# export CLIENT_SECRET='YOUR-CLIENT-SECRET'
client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://example.com"
# Set the scopes
scopes = ["tweet.read", "users.read", "offline.access"]
def main():
# Step 1: Create PKCE instance
auth = OAuth2PKCEAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scopes
)
# Step 2: Get authorization URL
auth_url = auth.get_authorization_url()
print("Visit the following URL to authorize your App on behalf of your X handle in a browser:")
print(auth_url)
# Step 3: Handle callback
callback_url = input("Paste the full callback URL here: ")
# Step 4: Exchange code for tokens
tokens = auth.fetch_token(authorization_response=callback_url)
access_token = tokens["access_token"]
# Step 5: Create client
client = Client(access_token=access_token)
# Step 6: Get authenticated user ID
me_response = client.users.get_me()
user_id = me_response.data["id"]
# Step 7: Get reverse chronological timeline with automatic pagination
# Post fields are adjustable. Options include:
# attachments, author_id, context_annotations, conversation_id,
# created_at, entities, geo, id, in_reply_to_user_id, lang,
# possibly_sensitive, public_metrics, referenced_tweets, source, text
all_posts = []
for page in client.users.get_timeline(
user_id,
max_results=100,
tweet_fields=["created_at"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_posts.extend(page_data)
print(f"Fetched {len(page_data)} posts (total: {len(all_posts)})")
print(f"\nTotal Posts: {len(all_posts)}")
print(json.dumps({"data": all_posts[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/users/timeline/get_mentions.py
================================================
"""
User Mentions Timeline - X API v2
==================================
Endpoint: GET https://api.x.com/2/users/:id/mentions
Docs: https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-mentions
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with user ID below
user_id = "2244994945"
def main():
# Get user mentions with automatic pagination
# Tweet fields are adjustable.
# Options include:
# attachments, author_id, context_annotations,
# conversation_id, created_at, entities, geo, id,
# in_reply_to_user_id, lang, non_public_metrics, organic_metrics,
# possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets,
# source, text, and withheld
all_posts = []
for page in client.users.get_mentions(
user_id,
max_results=100,
tweet_fields=["created_at"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_posts.extend(page_data)
print(f"Fetched {len(page_data)} posts (total: {len(all_posts)})")
print(f"\nTotal Mentions: {len(all_posts)}")
print(json.dumps({"data": all_posts[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/users/timeline/get_posts.py
================================================
"""
User Posts Timeline - X API v2
==============================
Endpoint: GET https://api.x.com/2/users/:id/tweets
Docs: https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets
Authentication: Bearer Token (App-only) or OAuth (User Context)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with the user ID you want to get posts for
user_id = "2244994945"
def main():
# Get user posts with automatic pagination
# Post fields are adjustable. Options include:
# attachments, author_id, context_annotations, conversation_id,
# created_at, entities, geo, id, in_reply_to_user_id, lang,
# non_public_metrics, organic_metrics, possibly_sensitive,
# promoted_metrics, public_metrics, referenced_tweets, source, text, and withheld
all_posts = []
for page in client.users.get_posts(
user_id,
max_results=100,
tweet_fields=["created_at"]
):
# Access data attribute (model uses extra='allow' so data should be available)
# Use getattr with fallback in case data field is missing from response
page_data = getattr(page, 'data', []) or []
all_posts.extend(page_data)
print(f"Fetched {len(page_data)} posts (total: {len(all_posts)})")
print(f"\nTotal Posts: {len(all_posts)}")
print(json.dumps({"data": all_posts[:5]}, indent=4, sort_keys=True)) # Print first 5 as example
if __name__ == "__main__":
main()
================================================
FILE: python/webhooks/delete_webhook.py
================================================
"""
Delete Webhook - X API v2
=========================
Endpoint: DELETE https://api.x.com/2/webhooks/:webhook_id
Docs: https://docs.x.com/x-api/webhooks/introduction
Deletes a registered webhook. After deletion, X will stop delivering events
to the associated URL. Use list_webhooks.py to find your webhook_id.
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with the webhook ID you wish to delete.
# You can find your webhook IDs by running list_webhooks.py
webhook_id = "your-webhook-id"
def main():
response = client.webhooks.delete(webhook_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/webhooks/list_webhooks.py
================================================
"""
List Webhooks - X API v2
========================
Endpoint: GET https://api.x.com/2/webhooks
Docs: https://docs.x.com/x-api/webhooks/introduction
Returns all registered webhooks for your app. Use the webhook_id from the
response when managing subscriptions or deleting a webhook.
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
def main():
response = client.webhooks.get()
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/webhooks/register_webhook.py
================================================
"""
Register Webhook - X API v2
===========================
Endpoint: POST https://api.x.com/2/webhooks
Docs: https://docs.x.com/x-api/webhooks/introduction
Registers a new webhook URL with X. When you make this request, X immediately
sends a CRC challenge GET request to your URL to verify ownership. Your server
must respond correctly before the webhook is saved — see webhook_server.py.
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with your publicly accessible HTTPS webhook URL.
# The URL must be reachable by X at the time of registration so the CRC check can complete.
# For local development you can use a tool like ngrok to expose a local server.
webhook_url = "https://your-domain.com/webhooks"
def main():
payload = {"url": webhook_url}
response = client.webhooks.create(body=payload)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/webhooks/validate_webhook.py
================================================
"""
Validate Webhook (Trigger CRC) - X API v2
==========================================
Endpoint: PUT https://api.x.com/2/webhooks/:webhook_id
Docs: https://docs.x.com/x-api/webhooks/introduction
Manually triggers a CRC (Challenge-Response Check) for the specified webhook.
Use this to re-validate your server's ownership or to re-enable a webhook that
was disabled due to failed CRC checks. Your webhook server must be running and
able to respond to the challenge before calling this endpoint.
Authentication: Bearer Token (App-only)
Required env vars: BEARER_TOKEN
"""
import os
import json
from xdk import Client
bearer_token = os.environ.get("BEARER_TOKEN")
client = Client(bearer_token=bearer_token)
# Replace with the webhook ID you wish to validate.
# You can find your webhook IDs by running list_webhooks.py
webhook_id = "your-webhook-id"
def main():
response = client.webhooks.validate(webhook_id)
print("Response code: 200")
print(json.dumps(response.data, indent=4, sort_keys=True))
if __name__ == "__main__":
main()
================================================
FILE: python/webhooks/webhook_server.py
================================================
"""
Webhook Server - X API v2
=========================
Docs: https://docs.x.com/x-api/webhooks/introduction
This is a minimal webhook consumer server that handles two responsibilities:
1. CRC (Challenge-Response Check) validation via GET — X sends a crc_token
and expects back an HMAC-SHA256 hash signed with your Consumer Secret.
This is required when registering a webhook and periodically thereafter
to confirm your server is still alive.
2. Event delivery via POST — X sends account activity or filtered stream
events as JSON payloads to this endpoint in real time.
To receive events you must:
1. Run this server at a publicly accessible HTTPS URL (e.g. via ngrok).
2. Register the URL with X: see register_webhook.py
3. Subscribe user accounts or set stream rules to start receiving events.
Authentication: Consumer Secret (HMAC-SHA256 for CRC validation)
Required env vars: CONSUMER_SECRET
Dependencies: flask, waitress (pip install flask waitress)
"""
import base64
import hashlib
import hmac
import json
import os
import sys
from flask import Flask, jsonify, request
from waitress import serve
app = Flask(__name__)
# Your app's Consumer Secret — used to sign the CRC response.
# To set environment variables on macOS or Linux, run the export commands below from the terminal:
# export CONSUMER_SECRET='YOUR-CONSUMER-SECRET'
CONSUMER_SECRET = os.environ.get("CONSUMER_SECRET")
if CONSUMER_SECRET is None:
print("Missing consumer secret. Ensure CONSUMER_SECRET env var is set.")
sys.exit(1)
HOST = "0.0.0.0"
PORT = 8080
@app.route('/webhooks', methods=['GET', 'POST'])
def webhook_request():
# Handle GET request (CRC challenge)
if request.method == 'GET':
crc_token = request.args.get('crc_token')
print(f"CRC Token received: {crc_token}")
if crc_token is None:
print("Error: No crc_token found in the request.")
return jsonify({'error': 'No crc_token'}), 400
# Creates HMAC SHA-256 hash from the incoming token and your Consumer Secret
sha256_hash_digest = hmac.new(
CONSUMER_SECRET.encode('utf-8'),
msg=crc_token.encode('utf-8'),
digestmod=hashlib.sha256
).digest()
# Construct response data with base64 encoded hash
response = {
'response_token': 'sha256=' + base64.b64encode(sha256_hash_digest).decode('utf-8')
}
# Returns properly formatted json response
return jsonify(response)
# Handle POST request (webhook event delivery)
elif request.method == 'POST':
event_data = request.get_json()
if event_data:
print(json.dumps(event_data, indent=2))
else:
# Log if the request body wasn't JSON or was empty
print(f"Body: {request.data.decode('utf-8')}")
# Return 200 OK immediately to acknowledge receipt.
# X will retry delivery if it does not receive a 2xx response promptly.
return '', 200
return 'Method Not Allowed', 405
def main():
print("--- Starting Webhook Server ---")
print(f"Listening on {HOST}:{PORT}")
print("Expose this server publicly (e.g. via ngrok) then register the URL with register_webhook.py")
serve(app, host=HOST, port=PORT)
if __name__ == '__main__':
main()
================================================
FILE: r/posts/full-archive-search.r
================================================
library(httr)
# Replace the bearer token below with
bearer_token = ""
headers = c(
`Authorization` = sprintf('Bearer %s', bearer_token)
)
params = list(
`query` = 'from:twitterdev lang:en',
`max_results` = '10',
`tweet.fields` = 'created_at,lang,context_annotations'
)
response <- httr::GET(url = 'https://api.x.com/2/tweets/search/all', httr::add_headers(.headers=headers), query = params)
fas_body <-
content(
response,
as = 'parsed',
type = 'application/json',
simplifyDataFrame = TRUE
)
View(fas_body$data)
================================================
FILE: r/posts/full_archive_tweet_counts.r
================================================
library(httr)
# Replace the bearer token below with
bearer_token = ""
headers = c(
`Authorization` = sprintf('Bearer %s', bearer_token)
)
params = list(
`query` = 'from:twitterdev',
`granularity` = 'day'
)
response <- httr::GET(url = 'https://api.x.com/2/tweets/counts/all', httr::add_headers(.headers=headers), query = params)
body <-
content(
response,
as = 'parsed',
type = 'application/json',
simplifyDataFrame = TRUE
)
View(body$data)
================================================
FILE: r/posts/recent-search.r
================================================
require(httr)
bearer_token = ""
headers = c(
`Authorization` = sprintf('Bearer %s', bearer_token)
)
params = list(
`query` = 'from:TwitterDev',
`max_results` = '10',
`tweet.fields` = 'created_at,lang,conversation_id'
)
response <- httr::GET(url = 'https://api.x.com/2/tweets/search/recent', httr::add_headers(.headers=headers), query = params)
recent_search_body <-
content(
response,
as = 'parsed',
type = 'application/json',
simplifyDataFrame = TRUE
)
View(recent_search_body$data)
================================================
FILE: r/posts/recent_tweet_counts.r
================================================
library(httr)
# Replace the bearer token below with
bearer_token = ""
headers = c(
`Authorization` = sprintf('Bearer %s', bearer_token)
)
params = list(
`query` = 'from:twitterdev',
`granularity` = 'day'
)
response <- httr::GET(url = 'https://api.x.com/2/tweets/counts/recent', httr::add_headers(.headers=headers), query = params)
body <-
content(
response,
as = 'parsed',
type = 'application/json',
simplifyDataFrame = TRUE
)
View(body$data)
================================================
FILE: r/users/get_users_with_bearer_token.r
================================================
require(httr)
bearer_token <- ""
headers <- c(`Authorization` = sprintf('Bearer %s', bearer_token))
params <- list(`user.fields` = 'description')
handle <- 'TwitterDev'
url_handle <-
sprintf('https://api.x.com/2/users/by?usernames=%s', handle)
response <-
httr::GET(url = url_handle,
httr::add_headers(.headers = headers),
query = params)
obj <- httr::content(res, as = "text")
print(obj)
================================================
FILE: ruby/Gemfile
================================================
source 'https://rubygems.org'
gem 'typhoeus', '~> 1.4'
gem 'oauth', '~> 1.1'
================================================
FILE: ruby/README.md
================================================
# X API v2 - Ruby Examples
Working Ruby code samples for the X (formerly Twitter) API v2.
## Setup
### 1. Install Ruby 2.7+
```bash
ruby --version
```
### 2. Install dependencies
```bash
bundle install
```
Or manually:
```bash
gem install typhoeus
gem install oauth # For OAuth 1.0a examples
```
The `Gemfile` includes:
- `typhoeus` (~> 1.4) - HTTP client library
- `oauth` (~> 1.1) - OAuth 1.0a library
### 3. Set environment variables
**For read-only operations (search, lookup):**
```bash
export BEARER_TOKEN='your_bearer_token'
```
**For user actions (post, like, repost, bookmark, etc.):**
```bash
export CLIENT_ID='your_client_id'
export CLIENT_SECRET='your_client_secret'
```
**For OAuth 1.0a (legacy endpoints):**
```bash
export CONSUMER_KEY='your_consumer_key'
export CONSUMER_SECRET='your_consumer_secret'
```
**Note:** Most user action examples require OAuth 2.0 authentication with `CLIENT_ID` and `CLIENT_SECRET`. Read-only examples (search, lookup) only require `BEARER_TOKEN`.
## Examples by Category
### Posts
- `posts/create_tweet.rb` - Create a new post
- `posts/delete_tweet.rb` - Delete a post
- `posts/full_archive_tweet_counts.rb` - Full archive tweet counts
- `posts/full-archive-search.rb` - Full archive search
- `posts/get_tweets_with_bearer_token.rb` - Look up posts by ID (bearer token)
- `posts/get_tweets_with_user_context.rb` - Look up posts by ID (user context)
- `posts/like_a_tweet.rb` - Like a post
- `posts/liked_tweets.rb` - Get posts liked by a user
- `posts/liking_users.rb` - Get users who liked a post
- `posts/lookup.rb` - Look up posts by ID
- `posts/quote_tweets.rb` - Get posts that quote a post
- `posts/recent_search.rb` - Recent search (last 7 days)
- `posts/recent_tweet_counts.rb` - Recent tweet counts
- `posts/retweet_a_tweet.rb` - Repost a post
- `posts/retweeted_by.rb` - Get users who reposted a post
- `posts/search_recent.rb` - Recent search (alternative)
- `posts/undo_a_retweet.rb` - Undo a repost
- `posts/unlike_a_tweet.rb` - Unlike a post
### Users
- `users/block_a_user.rb` - Block a user
- `users/followers-lookup.rb` - Get user's followers (lookup)
- `users/followers.rb` - Get user's followers
- `users/following-lookup.rb` - Get users a user is following
- `users/get_users_me_with_user_context.rb` - Get authenticated user (me)
- `users/get_users_with_bearer_token.rb` - Look up users by username (bearer token)
- `users/get_users_with_user_context.rb` - Look up users by username (user context)
- `users/lookup_blocks.rb` - Get users blocked by a user
- `users/lookup_mutes.rb` - Get users muted by a user
- `users/lookup.rb` - Look up users by username
- `users/mute_a_user.rb` - Mute a user
- `users/unblock_a_user.rb` - Unblock a user
- `users/unmute_a_user.rb` - Unmute a user
### Timelines
- `timelines/reverse-chron-home-timeline.rb` - Get home timeline (reverse chronological)
- `timelines/user_posts.rb` - Get user's posts timeline
- `timelines/user-mentions.rb` - Get user mentions timeline
- `timelines/user-tweets.rb` - Get user's tweets timeline
### Streams
- `streams/filtered_stream.rb` - Filtered stream with rules
- `streams/sampled_stream.rb` - Sampled stream
### Lists
- `lists/add_member.rb` - Add member to a list
- `lists/create_a_list.rb` - Create a new list
- `lists/delete_a_list.rb` - Delete a list
- `lists/follow_list.rb` - Follow a list
- `lists/list-followers-lookup.rb` - Get list followers
- `lists/list-lookup-by-id.rb` - Get list by ID
- `lists/list-member-lookup.rb` - Get list members
- `lists/List-Tweets.rb` - Get posts from a list
- `lists/lookup.rb` - Look up a list
- `lists/pin_list.rb` - Pin a list
- `lists/Pinned-List.rb` - Get pinned lists
- `lists/remove_member.rb` - Remove member from a list
- `lists/unfollow_list.rb` - Unfollow a list
- `lists/unpin_list.rb` - Unpin a list
- `lists/update_a_list.rb` - Update a list
- `lists/user-list-followed.rb` - Get lists followed by a user
- `lists/user-list-memberships.rb` - Get list memberships
- `lists/user-owned-list-lookup.rb` - Get lists owned by a user
### Bookmarks
- `bookmarks/bookmarks_lookup.rb` - Get user's bookmarks
### Spaces
- `spaces/search_spaces.rb` - Search for Spaces
- `spaces/spaces_lookup.rb` - Look up Spaces by ID
## Running Examples
```bash
# Make sure environment variables are set
ruby posts/search_recent.rb
```
## More Information
- [X API Documentation](https://developer.x.com/en/docs/twitter-api)
- [X Developer Portal](https://developer.x.com/en/portal/dashboard)
================================================
FILE: ruby/bookmarks/bookmarks_lookup.rb
================================================
require 'json'
require 'typhoeus'
require 'twitter_oauth2'
# First, you will need to enable OAuth 2.0 in your App’s auth settings in the Developer Portal to get your client ID.
# Inside your terminal you will need to set an enviornment variable
# export CLIENT_ID='your-client-id'
client_id = ENV["CLIENT_ID"]
# If you have selected a type of App that is a confidential client you will need to set a client secret.
# Confidential Clients securely authenticate with the authorization server.
# Inside your terminal you will need to set an enviornment variable
# export CLIENT_SECRET='your-client-secret'
# Remove the comment on the following line if you are using a confidential client
# client_secret = ENV["CLIENT_SECRET"]
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://www.example.com"
# Start an OAuth 2.0 session with a public client
client = TwitterOAuth2::Client.new(
identifier: "#{client_id}",
redirect_uri: "#{redirect_uri}"
)
# Start an OAuth 2.0 session with a confidential client
# Remove the comment on the following lines if you are using a confidential client
# client = TwitterOAuth2::Client.new(
# identifier: "#{client_id}",
# secret: "#{client_secret}",
# redirect_uri: "#{redirect_uri}"
# )
# Create your authorize url
authorization_url = client.authorization_uri(
# Update scopes if needed
scope: [
:'users.read',
:'tweet.read',
:'bookmark.read',
:'offline.access'
]
)
# Set code verifier and state
code_verifier = client.code_verifier
state = client.state
# Visit the URL to authorize your App to make requests on behalf of a user
print 'Visit the following URL to authorize your App on behalf of your Twitter handle in a browser'
puts authorization_url
`open "#{authorization_url}"`
print 'Paste in the full URL after you authorized your App: ' and STDOUT.flush
# Fetch your access token
full_text = gets.chop
new_code = full_text.split("code=")
code = new_code[1]
client.authorization_code = code
# Your access token
token_response = client.access_token! code_verifier
# Make a request to the users/me endpoint to get your user ID
def users_me(url, token_response)
options = {
method: 'get',
headers: {
"User-Agent": "BookmarksSampleCode",
"Authorization": "Bearer #{token_response}"
},
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
url = "https://api.x.com/2/users/me"
me_response = users_me(url, token_response)
json_s = JSON.parse(me_response.body)
user_id = json_s["data"]["id"]
# Make a request to the bookmarks url
bookmarks_url = "https://api.x.com/2/users/#{user_id}/bookmarks"
def bookmarked_tweets(bookmarks_url, token_response)
options = {
method: 'get',
headers: {
"User-Agent": "BookmarksSampleCode",
"Authorization": "Bearer #{token_response}"
}
}
request = Typhoeus::Request.new(bookmarks_url, options)
response = request.run
return response
end
response = bookmarked_tweets(bookmarks_url, token_response)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/List-Tweets.rb
================================================
# This script uses your bearer token to authenticate and retrieve the specified Tweet objects (by List ID)
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Be sure to replace list-id with any List ID
id = "list-id"
url = "https://api.x.com/2/lists/#{id}/tweets"
params = {
# Tweet fields are adjustable.
# Options include:
# attachments, author_id, context_annotations,
# conversation_id, created_at, entities, geo, id,
# in_reply_to_user_id, lang, non_public_metrics, organic_metrics,
# possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets,
# source, text, and withheld
"tweet.fields": "lang,author_id",
}
def list_tweets(url, bearer_token, params)
options = {
method: 'get',
headers: {
"User-Agent": "v2ListTweetsLookupRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = list_tweets(url, bearer_token, params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/Pinned-List.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
url = "https://api.x.com/2/users/#{id}/pinned_lists"
@params = {
# List fields are adjustable, options include:
# created_at, description, owner_id,
# private, follower_count, member_count,
"list.fields": "created_at,follower_count"
}
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def pin_list(url, oauth_params)
options = {
:method => :get,
headers: {
"User-Agent": "v2pinListLookupRuby",
"content-type": "application/json"
},
params: @params
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = pin_list(url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/add_member.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-list-id with your own list ID or one of an authenticating user
id = "your-list-id"
member_url = "https://api.x.com/2/lists/#{id}/members"
# Be sure to replace user-id-to-add with the user id you wish to add.
@user_id = { "user_id": "user-id-to-add" }
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def add_member(url, oauth_params)
options = {
:method => :post,
headers: {
"User-Agent": "v2addMemberRuby",
"content-type": "application/json"
},
body: JSON.dump(@user_id)
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = add_member(member_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/create_a_list.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
create_list_url = "https://api.x.com/2/lists"
# Be sure to add replace name-of-list with the name you wish to call the list.
# description and private keys are optional
@json_payload = { "name": "name-of-list",
"description": "description-of-list",
"private": false}
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def create_list(url, oauth_params)
options = {
:method => :post,
headers: {
"User-Agent": "v2createListRuby",
"content-type": "application/json"
},
body: JSON.dump(@json_payload)
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = create_list(create_list_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/delete_a_list.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-list-id with the id of the list you wish to delete. The authenticated user must own the list in order to delete
id = "your-list-id"
delete_list_url = "https://api.x.com/2/lists/#{id}"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def delete_list(url, oauth_params)
options = {
:method => :delete,
headers: {
"User-Agent": "v2deleteListRuby",
"content-type": "application/json"
}
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = delete_list(delete_list_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/follow_list.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
following_url = "https://api.x.com/2/users/#{id}/followed_lists"
# Be sure to add replace list-id-to-follow with the list id you wish to follow.
@list_id = { "list_id": "list-id-to-follow" }
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def follow_list(url, oauth_params)
options = {
:method => :post,
headers: {
"User-Agent": "v2followListRuby",
"content-type": "application/json"
},
body: JSON.dump(@list_id)
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = follow_list(following_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/list-followers-lookup.rb
================================================
# This script uses your bearer token to authenticate and retrieve followers of a List specified by List ID
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Be sure to replace list-id with any List ID
id = "list-id"
url = "https://api.x.com/2/lists/#{id}/followers"
params = {
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
"user.fields": "created_at,verified",
}
def lists(url, bearer_token, params)
options = {
method: 'get',
headers: {
"User-Agent": "v2ListFollowersLookupRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = lists(url, bearer_token, params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/list-lookup-by-id.rb
================================================
# This script uses your bearer token to authenticate and retrieve the specified List objects (by ID)
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Be sure to replace list-id with any List ID
id = "list-id"
url = "https://api.x.com/2/lists/#{id}"
params = {
# List fields are adjustable, options include:
# created_at, description, owner_id,
# private, follower_count, member_count,
"list.fields": "created_at,follower_count",
}
def lists(url, bearer_token, params)
options = {
method: 'get',
headers: {
"User-Agent": "v2ListLookupRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = lists(url, bearer_token, params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/list-member-lookup.rb
================================================
# This script uses your bearer token to authenticate and retrieve members of a List specified by List ID
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Be sure to replace list-id with any List ID
id = "list-id"
url = "https://api.x.com/2/lists/#{id}/members"
params = {
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
"user.fields": "created_at,verified",
}
def lists(url, bearer_token, params)
options = {
method: 'get',
headers: {
"User-Agent": "v2ListMembersLookupRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = lists(url, bearer_token, params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/lookup.rb
================================================
# List Lookup - X API v2
#
# Endpoint: GET https://api.x.com/2/lists/:id
# Docs: https://developer.x.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id
#
# Authentication: Bearer Token (App-only) or OAuth (User Context)
# Required env vars: BEARER_TOKEN
require 'json'
require 'typhoeus'
bearer_token = ENV["BEARER_TOKEN"]
# Replace with the list ID you want to look up
list_id = "84839422"
url = "https://api.x.com/2/lists/#{list_id}"
query_params = {
"list.fields": "created_at,follower_count,member_count,owner_id,description"
}
def lookup_list(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent": "v2ListLookupRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = lookup_list(url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/pin_list.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
pin_url = "https://api.x.com/2/users/#{id}/pinned_lists"
# Be sure to add replace list-id-to-pin with the list id you wish to pin.
@list_id = { "list_id": "list-id-to-pin" }
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def pin_list(url, oauth_params)
options = {
:method => :post,
headers: {
"User-Agent": "v2pinListRuby",
"content-type": "application/json"
},
body: JSON.dump(@list_id)
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = pin_list(pin_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/remove_member.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-list-id with your own list ID or one of an authenticating user
id = "your-list-id"
# Be sure to replace user-id-to-remove with the user id you wish to remove.
user_id = "user-id-to-remove"
member_url = "https://api.x.com/2/lists/#{id}/members/#{user_id}"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def remove_member(url, oauth_params)
options = {
:method => :delete,
headers: {
"User-Agent": "v2removeMemberRuby",
"content-type": "application/json"
}
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = remove_member(member_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/unfollow_list.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
# Be sure to add replace list-id-to-unfollow with the user id of the user you wish to unfollow.
list_id = "list-id-to-unfollow"
# Returns a user object for one or more users specified by the requested usernames
unfollow_url = "https://api.x.com/2/users/#{id}/followed_lists/#{list_id}"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def unfollow_list(url, oauth_params)
options = {
:method => :delete,
headers: {
"User-Agent": "v2unfollowListRuby"
}
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = unfollow_list(unfollow_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/unpin_list.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
# Be sure to add replace list-id-to-unpin with the user id of the user you wish to unpin.
list_id = "list-id-to-unpin"
# Returns a user object for one or more users specified by the requested usernames
unpin_url = "https://api.x.com/2/users/#{id}/pinned_lists/#{list_id}"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def unpin_list(url, oauth_params)
options = {
:method => :delete,
headers: {
"User-Agent": "v2unpinListRuby"
}
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = unpin_list(unpin_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/update_a_list.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to add replace update-name-of-list with the name you wish to call the list.
# name, description and private are all optional
@json_payload = { "name": "update-name-of-list-ruby",
"description": "update-description-of-list",
"private": false}
# Be sure to replace your-list-id with the id of the list you wish to update. The authenticated user must own the list in order to update
id = "your-list-id"
update_list_url = "https://api.x.com/2/lists/#{id}"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def update_list(url, oauth_params)
options = {
:method => :put,
headers: {
"User-Agent": "v2updateListRuby",
"content-type": "application/json"
},
body: JSON.dump(@json_payload)
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = update_list(update_list_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/user-list-followed.rb
================================================
# This script uses your bearer token to authenticate and retrieve the specified List objects (by user ID)
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Be sure to replace user-id with any User ID
id = "user-id"
url = "https://api.x.com/2/users/#{id}/followed_lists"
params = {
# List fields are adjustable, options include:
# created_at, description, owner_id,
# private, follower_count, member_count,
"list.fields": "created_at,private",
}
def lists(url, bearer_token, params)
options = {
method: 'get',
headers: {
"User-Agent": "v2userMembershipsRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = lists(url, bearer_token, params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/user-list-memberships.rb
================================================
# This script uses your bearer token to authenticate and retrieve the specified List objects (by user ID)
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Be sure to replace user-id with any User ID
id = "user-id"
url = "https://api.x.com/2/users/#{id}/list_memberships"
params = {
# List fields are adjustable, options include:
# created_at, description, owner_id,
# private, follower_count, member_count,
"list.fields": "created_at,private",
}
def lists(url, bearer_token, params)
options = {
method: 'get',
headers: {
"User-Agent": "v2userMembershipsRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = lists(url, bearer_token, params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/lists/user-owned-list-lookup.rb
================================================
# This script uses your bearer token to authenticate and retrieve any user owned Lists specified by user ID
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# You can replace the ID with the User ID to see if they own any Lists.
id = "user-id"
url = "https://api.x.com/2/users/#{id}/owned_lists"
params = {
# List fields are adjustable, options include:
# created_at, description, owner_id,
# private, follower_count, member_count,
"list.fields": "created_at,follower_count",
}
def lists(url, bearer_token, params)
options = {
method: 'get',
headers: {
"User-Agent": "v2ListLookupRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = lists(url, bearer_token, params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/create_tweet.rb
================================================
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
create_tweet_url = "https://api.x.com/2/tweets"
# Be sure to add replace the text of the with the text you wish to Tweet.
# You can also add parameters to post polls, quote Tweets, Tweet with reply settings, and Tweet to Super Followers in addition to other features.
@json_payload = {"text": "Hello world!"}
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def create_tweet(url, oauth_params)
options = {
:method => :post,
headers: {
"User-Agent": "v2CreateTweetRuby",
"content-type": "application/json"
},
body: JSON.dump(@json_payload)
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = create_tweet(create_tweet_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/delete_tweet.rb
================================================
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-tweet-id with the id of the Tweet you wish to delete.
id = "your-tweet-id"
delete_tweet_url = "https://api.x.com/2/tweets/#{id}"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def delete_tweet(url, oauth_params)
options = {
:method => :delete,
headers: {
"User-Agent": "v2DeleteTweetRuby",
"content-type": "application/json"
}
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = delete_tweet(delete_tweet_url, oauth_params)
================================================
FILE: ruby/posts/full-archive-search.rb
================================================
# This script uses your bearer token to authenticate and make a Search request
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Endpoint URL for the Full-archive Search API
search_url = "https://api.x.com/2/tweets/search/all"
# Set the query value here. Value can be up to 512 characters
query = "from:Twitter OR from:TwitterDev OR from:DailyNasa"
# Add or remove parameters below to adjust the query and response fields within the payload
# See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-all
query_params = {
"query": query, # Required
"max_results": 10,
# "start_time": "2020-07-01T00:00:00Z",
# "end_time": "2020-07-02T18:00:00Z",
# "expansions": "attachments.poll_ids,attachments.media_keys,author_id",
"tweet.fields": "attachments,author_id,conversation_id,created_at,entities,id,lang",
"user.fields": "description"
# "media.fields": "url",
# "place.fields": "country_code",
# "poll.fields": "options"
}
def search_tweets(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent": "v2FullArchiveSearchRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = search_tweets(search_url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/full_archive_tweet_counts.rb
================================================
# This script uses your bearer token to authenticate and make a Search request
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Endpoint URL for the Full-archive Search API
search_url = "https://api.x.com/2/tweets/counts/all"
# Set the query value here. Value can be up to 1024 characters
query = "from:TwitterDev"
# Add or remove parameters below to adjust the query and response fields within the payload
# See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-counts-all
query_params = {
"query": query, # Required
"start_time": "2021-01-01T00:00:00Z",
"granularity": "day"
}
def get_tweet_counts(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent": "v2FullArchiveTweetCountsRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = get_tweet_counts(search_url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/get_tweets_with_bearer_token.rb
================================================
# This script uses your bearer token to authenticate and retrieve the specified Tweet objects (by ID)
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
tweet_lookup_url = "https://api.x.com/2/tweets"
# Specify the Tweet IDs that you want to lookup below (to 100 per request)
tweet_ids = "1261326399320715264,1278347468690915330"
# Add or remove optional parameters values from the params object below. Full list of parameters and their values can be found in the docs:
# https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/api-reference
params = {
"ids": tweet_ids,
# "expansions": "author_id,referenced_tweets.id",
"tweet.fields": "attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang",
# "user.fields": "name"
# "media.fields": "url",
# "place.fields": "country_code",
# "poll.fields": "options"
}
def tweet_lookup(url, bearer_token, params)
options = {
method: 'get',
headers: {
"User-Agent": "v2TweetLookupRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = tweet_lookup(tweet_lookup_url, bearer_token, params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/get_tweets_with_user_context.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a Tweet lookup request (by IDs) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Returns a Tweet object for one or more Tweets IDs as specified by the request
tweet_lookup_url = "https://api.x.com/2/tweets"
# Specify the Tweet IDs that you want to lookup below (to 100 per request)
tweet_ids = "1261326399320715264,1278347468690915330"
# Add or remove optional parameters values from the params object below. Full list of parameters and their values can be found in the docs:
# https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/api-reference
query_params = {
"ids": tweet_ids,
# "expansions": "author_id,referenced_tweets.id",
"tweet.fields": "attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang",
# "user.fields": "name"
# "media.fields": "url",
# "place.fields": "country_code",
# "poll.fields": "options"
}
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def tweet_lookup(url, oauth_params, query_params)
options = {
:method => :get,
headers: {
"User-Agent": "v2TweetLookupRuby"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = tweet_lookup(tweet_lookup_url, oauth_params, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/like_a_tweet.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
likes_url = "https://api.x.com/2/users/#{id}/likes"
# You can replace Tweet ID given with the Tweet ID you wish to like.
# You can find a Tweet ID by using the Tweet lookup endpoint
@tweet_id = { "tweet_id": "1354143047324299264" }
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def user_like(url, oauth_params)
options = {
:method => :post,
headers: {
"User-Agent": "v2LikeTweetRuby",
"content-type": "application/json"
},
body: JSON.dump(@tweet_id)
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = user_like(likes_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/liked_tweets.rb
================================================
# This script uses your bearer token to authenticate and retrieve the specified User objects (by ID)
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
url = "https://api.x.com/2/users/#{id}/liked_tweets"
params = {
# Tweet fields are adjustable.
# Options include:
# attachments, author_id, context_annotations,
# conversation_id, created_at, entities, geo, id,
# in_reply_to_user_id, lang, non_public_metrics, organic_metrics,
# possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets,
# source, text, and withheld
"tweet.fields": "lang,author_id",
}
def liked_tweets(url, bearer_token, params)
options = {
method: 'get',
headers: {
"User-Agent": "v2LikedTweetsRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = liked_tweets(url, bearer_token, params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/liking_users.rb
================================================
# This script uses your bearer token to authenticate and retrieve the specified User objects (by ID)
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# You can replace the ID given with the Tweet ID you wish to like.
# You can find an ID by using the Tweet lookup endpoint
id = "1354143047324299264"
url = "https://api.x.com/2/tweets/#{id}/liking_users"
params = {
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
"user.fields": "created_at,description",
}
def liking_users(url, bearer_token, params)
options = {
method: 'get',
headers: {
"User-Agent": "v2LikingUsersRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = liking_users(url, bearer_token, params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/lookup.rb
================================================
# Post Lookup - X API v2
#
# Endpoint: GET https://api.x.com/2/tweets
# Docs: https://developer.x.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets
#
# Authentication: Bearer Token (App-only) or OAuth (User Context)
# Required env vars: BEARER_TOKEN
require 'json'
require 'typhoeus'
bearer_token = ENV["BEARER_TOKEN"]
# Post IDs to look up (comma-separated, up to 100)
post_ids = "1278747501642657792,1255542774432063488"
url = "https://api.x.com/2/tweets"
query_params = {
"ids": post_ids,
"tweet.fields": "created_at,author_id,lang,source,public_metrics"
}
def lookup_posts(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent": "v2PostLookupRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = lookup_posts(url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/quote_tweets.rb
================================================
# This script uses your bearer token to authenticate and make a request to the Quote Tweets endpoint.
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Endpoint URL for the Quote Tweets endpoint.
endpoint_url = "https://api.x.com/2/tweets/:id/quote_tweets"
# Specify the Tweet ID for this request.
id = 20
# Add or remove parameters below to adjust the query and response fields within the payload
# TODO: See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/
query_params = {
"max_results" => 100,
"expansions" => "attachments.poll_ids,attachments.media_keys,author_id",
"tweet.fields" => "attachments,author_id,conversation_id,created_at,entities,id,lang",
"user.fields" => "description"
}
def get_quote_tweets(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent" => "v2RubyExampleCode",
"Authorization" => "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
endpoint_url = endpoint_url.gsub(':id',id.to_s())
response = get_quote_tweets(endpoint_url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/recent_search.rb
================================================
# This script uses your bearer token to authenticate and make a Search request
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Endpoint URL for the Recent Search API
search_url = "https://api.x.com/2/tweets/search/recent"
# Set the query value here. Value can be up to 512 characters
query = "from:Twitter OR from:TwitterDev OR from:DailyNasa"
# Add or remove parameters below to adjust the query and response fields within the payload
# See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent
query_params = {
"query": query, # Required
"max_results": 10,
# "start_time": "2020-07-01T00:00:00Z",
# "end_time": "2020-07-02T18:00:00Z",
# "expansions": "attachments.poll_ids,attachments.media_keys,author_id",
"tweet.fields": "attachments,author_id,conversation_id,created_at,entities,id,lang",
"user.fields": "description"
# "media.fields": "url",
# "place.fields": "country_code",
# "poll.fields": "options"
}
def search_tweets(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent": "v2RecentSearchRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = search_tweets(search_url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/recent_tweet_counts.rb
================================================
# This script uses your bearer token to authenticate and make a Search request
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Endpoint URL for the Recent Search API
search_url = "https://api.x.com/2/tweets/counts/recent"
# Set the query value here. Value can be up to 512 characters
query = "from:TwitterDev"
# Add or remove parameters below to adjust the query and response fields within the payload
# See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-counts-recent
query_params = {
"query": query, # Required
"granularity": "day"
}
def get_tweet_counts(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent": "v2RecentTweetCountsRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = get_tweet_counts(search_url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/retweet_a_tweet.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to add replace id of the user you wish to retweet on behalf of.
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
retweets_url = "https://api.x.com/2/users/#{id}/retweets"
# Be sure to replace tweet-id with your the Tweet ID you want to retweet
# You can find a Tweet ID by using the Tweet lookup endpoint
@tweet_id = { "tweet_id": "1412865600439738368" }
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def user_retweet(url, oauth_params)
options = {
:method => :post,
headers: {
"User-Agent": "v2retweetUserRuby",
"content-type": "application/json"
},
body: JSON.dump(@tweet_id)
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = user_retweet(retweets_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/retweeted_by.rb
================================================
# This script uses your bearer token to authenticate and retrieve the specified User objects (by ID)
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# You can replace the ID given with the Tweet ID you wish to lookup Retweeting users for
# You can find an ID by using the Tweet lookup endpoint
id = "1412865600439738368"
url = "https://api.x.com/2/tweets/#{id}/retweeted_by"
params = {
# User fields are adjustable, options include:
# created_at, description, entities, id, location, name,
# pinned_tweet_id, profile_image_url, protected,
# public_metrics, url, username, verified, and withheld
"user.fields": "created_at,description",
}
def retweeted_by_users(url, bearer_token, params)
options = {
method: 'get',
headers: {
"User-Agent": "v2RetweetedbyUsersRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = retweeted_by_users(url, bearer_token, params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/search_recent.rb
================================================
# Recent Search - X API v2
#
# Endpoint: GET https://api.x.com/2/tweets/search/recent
# Docs: https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent
#
# Authentication: Bearer Token (App-only)
# Required env vars: BEARER_TOKEN
#
# Note: Returns posts from the last 7 days.
require 'json'
require 'typhoeus'
bearer_token = ENV["BEARER_TOKEN"]
search_url = "https://api.x.com/2/tweets/search/recent"
# Set the query value here. Value can be up to 512 characters
query = "from:XDevelopers -is:retweet"
# See docs for list of param options:
# https://developer.x.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent
query_params = {
"query": query,
"max_results": 10,
"tweet.fields": "attachments,author_id,conversation_id,created_at,entities,id,lang",
"user.fields": "description"
}
def search_posts(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent": "v2RecentSearchRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = search_posts(search_url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/undo_a_retweet.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
# You can replace the given Tweet ID with your the Tweet ID you want to Retweet
# You can find a Tweet ID by using the Tweet lookup endpoint
source_tweet_id = "1412865600439738368"
# Returns a user object for one or more users specified by the requested usernames
user_unretweet_url = "https://api.x.com/2/users/#{id}/retweets/#{source_tweet_id}"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def user_unretweet(url, oauth_params)
options = {
:method => :delete,
headers: {
"User-Agent": "v2UndoRetweetUserRuby"
}
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = user_unretweet(user_unretweet_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/posts/unlike_a_tweet.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticated user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
# You can replace Tweet ID given with the Tweet ID you wish to like.
# You can find a Tweet ID by using the Tweet lookup endpoint
tweet_id = "1354143047324299264"
# Returns a user object for one or more users specified by the requested usernames
tweet_unlike_url = "https://api.x.com/2/users/#{id}/likes/#{tweet_id}"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def tweet_unlike(url, oauth_params)
options = {
:method => :delete,
headers: {
"User-Agent": "v2UnlikeTweetRuby"
}
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = tweet_unlike(tweet_unlike_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/spaces/search_spaces.rb
================================================
# This script uses your bearer token to authenticate and make a Spaces lookup request
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on macOS, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Endpoint URL
spaces_search_url = "https://api.x.com/2/spaces/search"
# Replace this value with your search term
query = "NBA"
# Add or remove parameters below to adjust the query and response fields within the payload
# See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/spaces/search/api-reference
query_params = {
"query": query, # Required
"space.fields": 'title,created_at',
'expansions': 'creator_id'
}
def get_space(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent": "v2SpacesSearchRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = get_space(spaces_search_url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/spaces/spaces_lookup.rb
================================================
# This script uses your bearer token to authenticate and make a Spaces lookup request
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on macOS, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Endpoint URL for Spaces lookup
spaces_lookup_url = "https://api.x.com/2/spaces"
# Replace SPACE_ID with the ID of a Space
id = "SPACE_ID"
# Add or remove parameters below to adjust the query and response fields within the payload
# See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference
query_params = {
"ids": id, # Required
"space.fields": 'title,created_at',
'expansions': 'creator_id'
}
def get_space(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent": "v2SpacesLookupRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = get_space(spaces_lookup, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/streams/filtered_stream.rb
================================================
# This script contains methods to add, remove, and retrieve rules from your stream.
# It will also connect to the stream endpoint and begin outputting data.
# Run as-is, the script gives you the option to replace existing rules with new ones and begin streaming data
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
@bearer_token = ENV["BEARER_TOKEN"]
@stream_url = "https://api.x.com/2/tweets/search/stream"
@rules_url = "https://api.x.com/2/tweets/search/stream/rules"
@sample_rules = [
{ 'value': 'dog has:images', 'tag': 'dog pictures' },
{ 'value': 'cat has:images -grumpy', 'tag': 'cat pictures' },
]
# Add or remove values from the optional parameters below. Full list of parameters can be found in the docs:
# https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream
params = {
"expansions": "attachments.poll_ids,attachments.media_keys,author_id,entities.mentions.username,geo.place_id,in_reply_to_user_id,referenced_tweets.id,referenced_tweets.id.author_id",
"tweet.fields": "attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang",
# "user.fields": "description",
# "media.fields": "url",
# "place.fields": "country_code",
# "poll.fields": "options"
}
# Get request to rules endpoint. Returns list of of active rules from your stream
def get_all_rules
@options = {
headers: {
"User-Agent": "v2FilteredStreamRuby",
"Authorization": "Bearer #{@bearer_token}"
}
}
@response = Typhoeus.get(@rules_url, @options)
raise "An error occurred while retrieving active rules from your stream: #{@response.body}" unless @response.success?
@body = JSON.parse(@response.body)
end
# Post request to add rules to your stream
def set_rules(rules)
return if rules.nil?
@payload = {
add: rules
}
@options = {
headers: {
"User-Agent": "v2FilteredStreamRuby",
"Authorization": "Bearer #{@bearer_token}",
"Content-type": "application/json"
},
body: JSON.dump(@payload)
}
@response = Typhoeus.post(@rules_url, @options)
raise "An error occurred while adding rules: #{@response.status_message}" unless @response.success?
end
# Post request with a delete body to remove rules from your stream
def delete_all_rules(rules)
return if rules.nil?
@ids = rules['data'].map { |rule| rule["id"] }
@payload = {
delete: {
ids: @ids
}
}
@options = {
headers: {
"User-Agent": "v2FilteredStreamRuby",
"Authorization": "Bearer #{@bearer_token}",
"Content-type": "application/json"
},
body: JSON.dump(@payload)
}
@response = Typhoeus.post(@rules_url, @options)
raise "An error occurred while deleting your rules: #{@response.status_message}" unless @response.success?
end
# Helper method that gets active rules and prompts to delete (y/n), then adds new rules set in line 17 (@sample_rules)
def setup_rules
# Gets the complete list of rules currently applied to the stream
@rules = get_all_rules
puts "Found existing rules on the stream:\n #{@rules}\n"
puts "Do you want to delete existing rules and replace with new rules? [y/n]"
answer = gets.chomp
if answer == "y"
# Delete all rules
delete_all_rules(@rules)
else
puts "Keeping existing rules and adding new ones."
end
# Add rules to the stream
set_rules(@sample_rules)
end
# Connects to the stream and returns data (Tweet payloads) in chunks
def stream_connect(params)
@options = {
timeout: 20,
method: 'get',
headers: {
"User-Agent": "v2FilteredStreamRuby",
"Authorization": "Bearer #{@bearer_token}"
},
params: params
}
@request = Typhoeus::Request.new(@stream_url, @options)
@request.on_body do |chunk|
puts chunk
end
@request.run
end
# Comment this line if you already setup rules and want to keep them
setup_rules
# Listen to the stream.
# This reconnection logic will attempt to reconnect when a disconnection is detected.
# To avoid rate limites, this logic implements exponential backoff, so the wait time
# will increase if the client cannot reconnect to the stream.
timeout = 0
while true
stream_connect(params)
sleep 2 ** timeout
timeout += 1
end
================================================
FILE: ruby/streams/sampled_stream.rb
================================================
# This script connects to the Sample stream endpoint and outputs data
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
stream_url = "https://api.x.com/2/tweets/sample/stream"
# Add or remove optional parameters values from the params object below. Full list of parameters and their values can be found in the docs:
# https://developer.twitter.com/en/docs/twitter-api/tweets/volume-streams/api-reference/get-tweets-sample-stream
params = {
# "expansions": "author_id,referenced_tweets.id",
"tweet.fields": "attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang",
# "user.fields": "name"
# "media.fields": "url",
# "place.fields": "country_code",
# "poll.fields": "options"
}
def stream_connect(url, bearer_token, params)
options = {
timeout: 20,
method: 'get',
headers: {
"User-Agent": "v2SampledStreamRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
request.on_body do |chunk|
puts chunk
end
request.run
end
# Listen to the stream.
# This reconnection logic will attempt to reconnect when a disconnection is detected.
# To avoid rate limites, this logic implements exponential backoff, so the wait time
# will increase if the client cannot reconnect to the stream.
timeout = 0
while true
stream_connect(stream_url, bearer_token, params)
sleep 2 ** timeout
timeout += 1
end
================================================
FILE: ruby/timelines/reverse-chron-home-timeline.rb
================================================
require 'json'
require 'typhoeus'
require 'twitter_oauth2'
# First, you will need to enable OAuth 2.0 in your App’s auth settings in the Developer Portal to get your client ID.
# Inside your terminal you will need to set an enviornment variable
# export CLIENT_ID='your-client-id'
client_id = ENV["CLIENT_ID"]
# If you have selected a type of App that is a confidential client you will need to set a client secret.
# Confidential Clients securely authenticate with the authorization server.
# Inside your terminal you will need to set an enviornment variable
# export CLIENT_SECRET='your-client-secret'
# Remove the comment on the following line if you are using a confidential client
# client_secret = ENV["CLIENT_SECRET"]
# Replace the following URL with your callback URL, which can be obtained from your App's auth settings.
redirect_uri = "https://www.example.com"
# Start an OAuth 2.0 session with a public client
client = TwitterOAuth2::Client.new(
identifier: "#{client_id}",
redirect_uri: "#{redirect_uri}"
)
# Start an OAuth 2.0 session with a confidential client
# Remove the comment on the following lines if you are using a confidential client
# client = TwitterOAuth2::Client.new(
# identifier: "#{client_id}",
# secret: "#{client_secret}",
# redirect_uri: "#{redirect_uri}"
# )
# Create your authorize url
authorization_url = client.authorization_uri(
# Update scopes if needed
scope: [
:'users.read',
:'tweet.read',
:'offline.access'
]
)
# Set code verifier and state
code_verifier = client.code_verifier
state = client.state
# Visit the URL to authorize your App to make requests on behalf of a user
print 'Visit the following URL to authorize your App on behalf of your Twitter handle in a browser'
puts authorization_url
`open "#{authorization_url}"`
print 'Paste in the full URL after you authorized your App: ' and STDOUT.flush
# Fetch your access token
full_text = gets.chop
new_code = full_text.split("code=")
code = new_code[1]
client.authorization_code = code
# Your access token
token_response = client.access_token! code_verifier
# Make a request to the users/me endpoint to get your user ID
def users_me(url, token_response)
options = {
method: 'get',
headers: {
"User-Agent": "ReverseChronHomeTimelineSampleCode",
"Authorization": "Bearer #{token_response}"
},
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
url = "https://api.x.com/2/users/me"
me_response = users_me(url, token_response)
json_s = JSON.parse(me_response.body)
user_id = json_s["data"]["id"]
# Make a request to the reverse chronological home timeline endpoint
url = "https://api.x.com/2/users/#{user_id}/timelines/reverse_chronological"
def reverse_chron_timeline(url, token_response)
options = {
method: 'get',
headers: {
"User-Agent": "ReverseChronTimelinesSampleCode",
"Authorization": "Bearer #{token_response}"
}
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = reverse_chron_timeline(url, token_response)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/timelines/user-mentions.rb
================================================
# This script uses your bearer token to authenticate and make a request to the User mentions timeline endpoint.
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Endpoint URL for the User mentions timelines.
endpoint_url = "https://api.x.com/2/users/:id/mentions"
# Specify the User ID for this request.
id = 2244994945 #@TwitterDev's numeric User ID.
# Add or remove parameters below to adjust the query and response fields within the payload
# TODO: See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/
query_params = {
"max_results" => 100,
# "start_time" => "2020-07-01T00:00:00Z",
# "end_time" => "2020-07-02T18:00:00Z",
"expansions" => "attachments.poll_ids,attachments.media_keys,author_id",
"tweet.fields" => "attachments,author_id,conversation_id,created_at,entities,id,lang",
"user.fields" => "description"
# "media.fields" => "url",
# "place.fields" => "country_code",
# "poll.fields" => "options"
}
def get_user_mentions(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent" => "v2RubyExampleCode",
"Authorization" => "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
endpoint_url = endpoint_url.gsub(':id',id.to_s())
response = get_user_mentions(endpoint_url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/timelines/user-tweets.rb
================================================
# This script uses your bearer token to authenticate and make a request to the User Tweets timeline endpoint.
#Based on recent search example and updated for User mention timeline.
#Next steps:
# [] Refactor for User Tweets timeline..
# [] Refactor for Full-archive search.
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Endpoint URL for the Recent Search API
endpoint_url = "https://api.x.com/2/users/:id/tweets"
# Specify the User ID for this request.
id = 2244994945 #@TwitterDev's numeric User ID.
# Add or remove parameters below to adjust the query and response fields within the payload
# TODO: See docs for list of param options: https://developer.twitter.com/en/docs/twitter-api/tweets/
query_params = {
"max_results" => 100,
# "start_time" => "2020-07-01T00:00:00Z",
# "end_time" => "2020-07-02T18:00:00Z",
"expansions" => "attachments.poll_ids,attachments.media_keys,author_id",
"tweet.fields" => "attachments,author_id,conversation_id,created_at,entities,id,lang",
"user.fields" => "description"
# "media.fields" => "url",
# "place.fields" => "country_code",
# "poll.fields" => "options"
}
def get_user_tweets(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent" => "v2RubyExampleCode",
"Authorization" => "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
endpoint_url = endpoint_url.gsub(':id',id.to_s())
response = get_user_tweets(endpoint_url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/timelines/user_posts.rb
================================================
# User Posts Timeline - X API v2
#
# Endpoint: GET https://api.x.com/2/users/:id/tweets
# Docs: https://developer.x.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets
#
# Authentication: Bearer Token (App-only) or OAuth (User Context)
# Required env vars: BEARER_TOKEN
require 'json'
require 'typhoeus'
bearer_token = ENV["BEARER_TOKEN"]
# Replace with the user ID you want to get posts for
user_id = "2244994945"
url = "https://api.x.com/2/users/#{user_id}/tweets"
query_params = {
"tweet.fields": "created_at,public_metrics",
"max_results": 10
}
def get_user_posts(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent": "v2UserPostsRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = get_user_posts(url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/users/block_a_user.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
blocking_url = "https://api.x.com/2/users/#{id}/blocking"
# Be sure to add replace id-to-block with the id of the user you wish to block.
# You can find a user ID by using the user lookup endpoint
@target_user_id = { "target_user_id": "id-to-block" }
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def user_block(url, oauth_params)
options = {
:method => :post,
headers: {
"User-Agent": "v2BlockUserRuby",
"content-type": "application/json"
},
body: JSON.dump(@target_user_id)
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = user_block(blocking_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/users/followers-lookup.rb
================================================
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on macOS or Linux, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Endpoint URL for the user followers
endpoint_url = "https://api.x.com/2/users/:id/followers"
# Specify the User ID for this request.
id = 2244994945
# Add or remove parameters below to adjust the query and response fields within the payload
query_params = {
"max_results" => 1000,
"user.fields" => "created_at"
}
def get_followers(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent" => "v2RubyExampleCode",
"Authorization" => "Bearer #{bearer_token}",
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
endpoint_url = endpoint_url.gsub(':id',id.to_s())
response = get_followers(endpoint_url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/users/followers.rb
================================================
# User Followers Lookup - X API v2
#
# Endpoint: GET https://api.x.com/2/users/:id/followers
# Docs: https://developer.x.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers
#
# Authentication: Bearer Token (App-only) or OAuth (User Context)
# Required env vars: BEARER_TOKEN
require 'json'
require 'typhoeus'
bearer_token = ENV["BEARER_TOKEN"]
# Replace with the user ID you want to get followers for
user_id = "2244994945"
url = "https://api.x.com/2/users/#{user_id}/followers"
query_params = {
"user.fields": "created_at,description",
"max_results": 100
}
def get_followers(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent": "v2FollowersRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = get_followers(url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/users/following-lookup.rb
================================================
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on macOS or Linux, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
# Endpoint URL for the user following API
endpoint_url = "https://api.x.com/2/users/:id/following"
# Specify the User ID for this request.
id = 2244994945
# Add or remove parameters below to adjust the query and response fields within the payload
query_params = {
"max_results" => 1000,
"user.fields" => "created_at"
}
def get_following(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent" => "v2RubyExampleCode",
"Authorization" => "Bearer #{bearer_token}",
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
endpoint_url = endpoint_url.gsub(':id',id.to_s())
response = get_following(endpoint_url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/users/get_users_me_with_user_context.rb
================================================
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
user_lookup_url = "https://api.x.com/2/users/me"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
# Add or remove optional parameters values from the params object below. Full list of parameters and their values can be found in the docs:
# https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users
query_params = {
# "expansions": "pinned_tweet_id",
# "tweet.fields": "attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang",
"user.fields": "created_at,description"
}
def user_lookup(url, oauth_params, query_params)
options = {
:method => :get,
headers: {
"User-Agent": "v2UserLookupRuby"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = user_lookup(user_lookup_url, oauth_params, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/users/get_users_with_bearer_token.rb
================================================
# This script uses your bearer token to authenticate and retrieve the specified User objects (by ID)
require 'json'
require 'typhoeus'
# The code below sets the bearer token from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export BEARER_TOKEN='YOUR-TOKEN'
bearer_token = ENV["BEARER_TOKEN"]
user_lookup_url = "https://api.x.com/2/users"
# Specify the User IDs that you want to lookup below (to 100 per request)
user_ids = "2244994945,783214"
# Add or remove optional parameters values from the params object below. Full list of parameters and their values can be found in the docs
params = {
"ids": user_ids,
"expansions": "pinned_tweet_id",
"tweet.fields": "attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang",
# "user.fields": "name"
# "media.fields": "url",
# "place.fields": "country_code",
# "poll.fields": "options"
}
def user_lookup(url, bearer_token, params)
options = {
method: 'get',
headers: {
"User-Agent": "v2UserLookupRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = user_lookup(user_lookup_url, bearer_token, params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/users/get_users_with_user_context.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Returns a user object for one or more users specified by the requested usernames
user_lookup_url = "https://api.x.com/2/users/by"
# Specify the usernames that you want to lookup below (to 100 per request)
usernames = "Twitter,TwitterDev"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
# Add or remove optional parameters values from the params object below. Full list of parameters and their values can be found in the docs:
# https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users
query_params = {
"usernames": usernames,
# "expansions": "pinned_tweet_id",
"tweet.fields": "attachments,author_id,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang",
# "user.fields": "name"
}
def user_lookup(url, oauth_params, query_params)
options = {
:method => :get,
headers: {
"User-Agent": "v2UserLookupRuby"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = user_lookup(user_lookup_url, oauth_params, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/users/lookup.rb
================================================
# User Lookup - X API v2
#
# Endpoint: GET https://api.x.com/2/users/by
# Docs: https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by
#
# Authentication: Bearer Token (App-only) or OAuth (User Context)
# Required env vars: BEARER_TOKEN
require 'json'
require 'typhoeus'
bearer_token = ENV["BEARER_TOKEN"]
url = "https://api.x.com/2/users/by"
# Usernames to look up (up to 100 comma-separated)
query_params = {
"usernames": "XDevelopers,X",
"user.fields": "created_at,description,public_metrics"
}
def lookup_users(url, bearer_token, query_params)
options = {
method: 'get',
headers: {
"User-Agent": "v2UserLookupRuby",
"Authorization": "Bearer #{bearer_token}"
},
params: query_params
}
request = Typhoeus::Request.new(url, options)
response = request.run
return response
end
response = lookup_users(url, bearer_token, query_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/users/lookup_blocks.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
blocking_url = "https://api.x.com/2/users/#{id}/blocking"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def user_block(url, oauth_params)
options = {
:method => :get,
headers: {
"User-Agent": "v2BlocksLookupRuby"
}
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = user_block(blocking_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/users/lookup_mutes.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a Mutes lookup request (by usernames) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
muting_url = "https://api.x.com/2/users/#{id}/muting"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def users_muted(url, oauth_params)
options = {
:method => :get,
headers: {
"User-Agent": "v2MutesLookupRuby"
}
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = users_muted(muting_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/users/mute_a_user.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
id = "your-user-id"
muting_url = "https://api.x.com/2/users/#{id}/muting"
# Be sure to add replace id-to-mute with the id of the user you wish to mute.
# You can find a user ID by using the user lookup endpoint
@target_user_id = { "target_user_id": "id-to-mute" }
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def user_mute(url, oauth_params)
options = {
:method => :post,
headers: {
"User-Agent": "v2muteUserRuby",
"content-type": "application/json"
},
body: JSON.dump(@target_user_id)
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = user_mute(muting_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
================================================
FILE: ruby/users/unblock_a_user.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
# It then makes a User lookup request (by usernames) with OAuth 1.0a authentication (user context)
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
source_user_id = "your-user-id"
# Be sure to add replace id-to-unblock with the user id of the user you wish to unblock.
# You can find a user ID by using the user lookup endpoint
target_user_id = "id-to-unblock"
# Returns a user object for one or more users specified by the requested usernames
user_unblock_url = "https://api.x.com/2/users/#{source_user_id}/blocking/#{target_user_id}"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def user_unblock(url, oauth_params)
options = {
:method => :delete,
headers: {
"User-Agent": "v2UnblockUserRuby"
}
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = user_unblock(user_unblock_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))
# Note: If you were following the user you blocked, you have removed your follow and will have to refollow the user, even if you did unblock the user.
================================================
FILE: ruby/users/unmute_a_user.rb
================================================
# This script implements the PIN-based OAuth flow to obtain access tokens for a user context request
require 'oauth'
require 'json'
require 'typhoeus'
require 'oauth/request_proxy/typhoeus_request'
# The code below sets the consumer key and secret from your environment variables
# To set environment variables on Mac OS X, run the export command below from the terminal:
# export CONSUMER_KEY='YOUR-KEY', CONSUMER_SECRET='YOUR-SECRET'
consumer_key = ENV["CONSUMER_KEY"]
consumer_secret = ENV["CONSUMER_SECRET"]
# Be sure to replace your-user-id with your own user ID or one of an authenticating user
# You can find a user ID by using the user lookup endpoint
source_user_id = "your-user-id"
# Be sure to add replace id-to-unmute with the user id of the user you wish to unmute.
# You can find a user ID by using the user lookup endpoint
target_user_id = "id-to-unmute"
# Returns a user object for one or more users specified by the requested usernames
user_unmute_url = "https://api.x.com/2/users/#{source_user_id}/muting/#{target_user_id}"
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
:site => 'https://api.x.com',
:authorize_path => '/oauth/authenticate',
:debug_output => false)
def get_request_token(consumer)
request_token = consumer.get_request_token()
return request_token
end
def get_user_authorization(request_token)
puts "Follow this URL to have a user authorize your app: #{request_token.authorize_url()}"
puts "Enter PIN: "
pin = gets.strip
return pin
end
def obtain_access_token(consumer, request_token, pin)
token = request_token.token
token_secret = request_token.secret
hash = { :oauth_token => token, :oauth_token_secret => token_secret }
request_token = OAuth::RequestToken.from_hash(consumer, hash)
# Get access token
access_token = request_token.get_access_token({:oauth_verifier => pin})
return access_token
end
def user_unmute(url, oauth_params)
options = {
:method => :delete,
headers: {
"User-Agent": "v2UnmuteUserRuby"
}
}
request = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
return response
end
# PIN-based OAuth flow - Step 1
request_token = get_request_token(consumer)
# PIN-based OAuth flow - Step 2
pin = get_user_authorization(request_token)
# PIN-based OAuth flow - Step 3
access_token = obtain_access_token(consumer, request_token, pin)
oauth_params = {:consumer => consumer, :token => access_token}
response = user_unmute(user_unmute_url, oauth_params)
puts response.code, JSON.pretty_generate(JSON.parse(response.body))