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 [![X API v2](https://img.shields.io/endpoint?url=https%3A%2F%2Ftwbadges.glitch.me%2Fbadges%2Fv2)](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))