twitter_api_v2

The Lightweight and Cross-Platform Wrapper for Twitter API v2.0 🐦


Awesome GitHub Sponsor GitHub Sponsor

v2 pub package Dart SDK Version Test Analyzer codecov Issues Pull Requests Stars Contributors Code size Last Commits License Contributor Covenant FOSSA Status


| English | ζ—₯本θͺž | FranΓ§ais | TiαΊΏng Việt | বাংলা | EspaΓ±ol | Deutsch |


1. Guide 🌎

This library provides the easiest way to use Twitter API v2.0 in Dart and Flutter apps.

Show some ❀️ and star the repo to support the project.

We also provide twitter_oauth2_pkce for easy OAuth 2.0 PKCE authentication when using the Twitter API!

1.1. Features πŸ’Ž

βœ… The wrapper library for Twitter API v2.0.
βœ… Easily integrates with the Dart & Flutter apps.
βœ… Provides response objects with a guaranteed safe types.
βœ… Supports all endpoints.
βœ… Support all request parameters and response fields.
βœ… Supports high-performance streaming endpoints.
βœ… Supports expansions and fields features.
βœ… Well documented and well tested.
βœ… Supports the powerful automatic retry.

1.2. Getting Started ⚑

1.2.1. Install Library

With Dart:

 dart pub add twitter_api_v2

Or With Flutter:

 flutter pub add twitter_api_v2

1.2.2. Import

import 'package:twitter_api_v2/twitter_api_v2';

1.2.3. Implementation

import 'dart:async';

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  //! You need to get keys and tokens at https://developer.twitter.com
  final twitter = v2.TwitterApi(
    //! Authentication with OAuth2.0 is the default.
    //!
    //! Note that to use endpoints that require certain user permissions,
    //! such as Tweets and Likes, you need a token issued by OAuth2.0 PKCE.
    //!
    //! The easiest way to achieve authentication with OAuth 2.0 PKCE is
    //! to use [twitter_oauth2_pkce](https://pub.dev/packages/twitter_oauth2_pkce)!
    bearerToken: 'YOUR_TOKEN_HERE',

    //! Or perhaps you would prefer to use the good old OAuth1.0a method
    //! over the OAuth2.0 PKCE method. Then you can use the following code
    //! to set the OAuth1.0a tokens.
    //!
    //! However, note that some endpoints cannot be used for OAuth 1.0a method
    //! authentication.
    oauthTokens: v2.OAuthTokens(
      consumerKey: 'YOUR_CONSUMER_KEY_HERE',
      consumerSecret: 'YOUR_CONSUMER_SECRET_HERE',
      accessToken: 'YOUR_ACCESS_TOKEN_HERE',
      accessTokenSecret: 'YOUR_ACCESS_TOKEN_SECRET_HERE',
    ),

    //! Automatic retry is available when a TimeoutException occurs when
    //! communicating with the API.
    retryConfig: v2.RetryConfig.regularIntervals(
      maxAttempts: 5,
      intervalInSeconds: 3,
    ),

    //! The default timeout is 10 seconds.
    timeout: Duration(seconds: 20),
  );

  try {
    // Get the authenticated user's profile.
    final me = await twitter.usersService.lookupMe();
    // Get the tweets associated with the search query.
    final tweets = await twitter.tweetsService.searchRecent(
      query: '#ElonMusk',
      maxResults: 20,
      // You can expand the search result.
      expansions: [
        v2.TweetExpansion.authorId,
        v2.TweetExpansion.inReplyToUserId,
      ],
      tweetFields: [
        v2.TweetField.conversationId,
        v2.TweetField.publicMetrics,
      ],
      userFields: [
        v2.UserField.location,
        v2.UserField.verified,
        v2.UserField.entities,
        v2.UserField.publicMetrics,
      ],
    );

    await twitter.tweetsService.createLike(
      userId: me.data.id,
      tweetId: tweets.data.first.id,
    );

    // High-performance Volume Stream endpoint is available.
    final volumeStream = await twitter.tweetsService.connectVolumeStream();
    await for (final response in volumeStream.handleError(print)) {
      print(response);
    }

    // Also high-performance Filtered Stream endpoint is available.
    await twitter.tweetsService.createFilteringRules(
      rules: [
        v2.FilteringRuleParam(value: '#ElonMusk'),
        v2.FilteringRuleParam(value: '#Tesla'),
        v2.FilteringRuleParam(value: '#SpaceX'),
      ],
    );

    final filteredStream = await twitter.tweetsService.connectFilteredStream();
    await for (final response in filteredStream.handleError(print)) {
      print(response.data);
      print(response.matchingRules);
    }
  } on TimeoutException catch (e) {
    print(e);
  } on v2.UnauthorizedException catch (e) {
    print(e);
  } on v2.RateLimitExceededException catch (e) {
    print(e);
  } on v2.TwitterException catch (e) {
    print(e.response.headers);
    print(e.body);
    print(e);
  }
}

1.3. Supported Endpoints πŸ‘€

1.3.1. Tweets Service

1.3.1.1. Tweet

Endpoint Method Name
POST /2/tweets createTweet
DELETE /2/tweets/:id destroyTweet

1.3.1.2. Likes

Endpoint Method Name
POST /2/users/:id/likes createLike
DELETE /2/users/:id/likes/:tweet_id destroyLike
GET /2/tweets/:id/liking_users lookupLikingUsers
GET /2/users/:id/liked_tweets lookupLikedTweets

1.3.1.3. Retweets

Endpoint Method Name
POST /2/users/:id/retweets createRetweet
DELETE /2/users/:id/retweets/:source_tweet_id destroyRetweet
GET /2/tweets/:id/retweeted_by lookupRetweetedUsers

1.3.1.4. Quote Tweets

Endpoint Method Name
GET /2/tweets/:id/quote_tweets lookupQuoteTweets

1.3.1.5. Search Tweets

Endpoint Method Name
GET /2/tweets/search/all searchAll
GET /2/tweets/search/recent searchRecent

1.3.1.6. Lookup Tweets

Endpoint Method Name
GET /2/tweets lookupByIds
GET /2/tweets/:id lookupById

1.3.1.7. Tweet Counts

Endpoint Method Name
GET /2/tweets/counts/all countAll
GET /2/tweets/counts/recent countRecent

1.3.1.8. Bookmarks

Endpoint Method Name
POST /2/users/:id/bookmarks createBookmark
DELETE /2/users/:id/bookmarks/:tweet_id destroyBookmark
GET /2/users/:id/bookmarks lookupBookmarks

1.3.1.9. Timelines

Endpoint Method Name
GET /2/users/:id/mentions lookupMentions
GET /2/users/:id/tweets lookupTweets
GET /2/users/:id/timelines/reverse_chronological lookupHomeTimeline

1.3.1.10. Hide Replies

Endpoint Method Name
PUT /2/tweets/:id/hidden createHiddenReply
PUT /2/tweets/:id/hidden destroyHiddenReply

1.3.1.11. Volume Stream

Endpoint Method Name
GET /2/tweets/sample/stream connectVolumeStream

1.3.1.12. Filtered Stream

Endpoint Method Name
POST /2/tweets/search/stream/rules createFilteringRules
GET /2/tweets/search/stream/rules lookupFilteringRules
GET /2/tweets/search/stream connectFilteredStream

1.3.2. Users Service

1.3.2.1. Follows

Endpoint Method Name
POST /2/users/:id/following createFollow
DELETE /2/users/:source_user_id/following/:target_user_id destroyFollow
GET /2/users/:id/followers lookupFollowers
GET /2/users/:id/following lookupFollowings

1.3.2.2. Lookup Users

Endpoint Method Name
GET /2/users lookupByIds
GET /2/users/:id lookupById
GET /2/users/by lookupByNames
GET /2/users/by/username/:username lookupByName
GET /2/users/me lookupMe

1.3.2.3. Users Mutes

Endpoint Method Name
POST /2/users/:id/muting createMute
DELETE /2/users/:source_user_id/muting/:target_user_id destroyMute
GET /2/users/:id/muting lookupMutingUsers

1.3.2.4. Blocks

Endpoint Method Name
POST /2/users/:id/blocking createBlock
DELETE /2/users/:source_user_id/blocking/:target_user_id destroyBlock
GET /2/users/:id/blocking lookupBlockingUsers

1.3.3. Spaces Service

1.3.3.1. Search Spaces

Endpoint Method Name
GET /2/spaces/search search

1.3.3.2. Lookup Spaces

Endpoint Method Name
GET /2/spaces lookupByIds
GET /2/spaces/:id lookupById
GET /2/spaces/:id/buyers lookupBuyers
GET /2/spaces/:id/tweets lookupTweets
GET /2/spaces/by/creator_ids lookupByCreatorIds

1.3.4. Lists Service

1.3.4.1. Lookup Lists

Endpoint Method Name
GET /2/lists/:id lookupById
GET /2/users/:id/owned_lists lookupOwnedBy

1.3.4.2. Pinnings

Endpoint Method Name
POST /2/users/:id/pinned_lists createPinnedList
DELETE /2/users/:id/pinned_lists/:list_id destroyPinnedList
GET /2/users/:id/pinned_lists lookupPinnedLists

1.3.4.3. Tweet Lookup

Endpoint Method Name
GET /2/lists/:id/tweets lookupTweets

1.3.4.4. List Manage

Endpoint Method Name
POST /2/lists createPublicList
POST /2/lists createPrivateList
DELETE /2/lists/:id destroyList
PUT /2/lists/:id updateListAsPublic
PUT /2/lists/:id updateListAsPrivate

1.3.4.5. Follows

Endpoint Method Name
POST /2/users/:id/followed_lists createFollow
DELETE /2/users/:id/followed_lists/:list_id destroyFollow
GET /2/lists/:id/followers lookupFollowers
GET /2/users/:id/followed_lists lookupFollowedLists

1.3.4.6. Members

Endpoint Method Name
POST /2/lists/:id/members createMember
DELETE /2/lists/:id/members/:user_id destroyMember
GET /2/lists/:id/members lookupMembers
GET /2/users/:id/list_memberships lookupMemberships

1.3.5. Compliance Service

1.3.5.1. Batch Compliance

Endpoint Method Name
POST /2/compliance/jobs createJob
GET /2/compliance/jobs lookupJobs
GET /2/compliance/jobs/:id lookupJob

1.4. Tips πŸ„

1.4.1. Method Names

twitter_api_v2 uses the following standard prefixes depending on endpoint characteristics. So it's very easy to find the method corresponding to the endpoint you want to use!

Prefix Description
lookup This prefix is attached to endpoints that reference tweets, users, etc.
search This prefix is attached to endpoints that perform extensive searches.
connect This prefix is attached to endpoints with high-performance streaming.
count This prefix is attached to the endpoint that counts a particular item.
create This prefix is attached to the endpoint performing the create state such as Tweet and Follow.
destroy This prefix is attached to the endpoint performing the destroy state such as Tweet and Follow.
update This prefix is attached to the endpoint performing the update state.

1.4.2. Generate App-Only Bearer Token

twitter_api_v2 provides utility to generate/find your app-only bearer token.

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final bearerToken = await v2.OAuthUtils.generateAppOnlyBearerToken(
    consumerKey: 'YOUR_CONSUMER_KEY',
    consumerSecret: 'YOUR_CONSUMER_SECRET',
  );

  print(bearerToken);
}

1.4.3. Null Parameter at Request

In this library, parameters that are not required at request time, i.e., optional parameters, are defined as nullable. However, developers do not need to be aware of the null parameter when sending requests when using this library.

It means the parameters specified with a null value are safely removed and ignored before the request is sent.

For example, arguments specified with null are ignored in the following request.

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(bearerToken: 'YOUR_TOKEN_HERE');

  await twitter.tweetsService.createTweet(
    text: 'Hello, World!',
    // These parameters are ignored at request because they are null.
    mediaIds: null,
    expansions: null,
  );
}

1.4.4. Expand Object Fields with expansions

For example, there may be a situation where data contains only an ID, and you want to retrieve the data object associated with that ID as well. In such cases, the Twitter API v2.0 specification called expansions is useful, and this library supports that specification.

Basically it can be used in endpoints that perform GET communication such as lookup and search processing. Some fields may also be included in the includes property of TwitterResponse.

You can use expansions like below:

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(bearerToken: 'YOUR_TOKEN_HERE');

  try {
    final tweets = await twitter.tweetsService.searchRecent(
      query: '#ElonMusk',
      // Specify fields you need!
      expansions: [
        v2.TweetExpansion.authorId,
        v2.TweetExpansion.inReplyToUserId,
      ],
    );

    print(tweets);
  } on v2.TwitterException catch (e) {
    print(e);
  }
}

You can see more details about expansions from Official Documentation.

1.4.5. Expand Object Fields with fields

Twitter API v2.0 supports a very interesting specification, allowing users to control the amount of data contained in the response object for each endpoint depending on the situation. It's called fields, and this library supports this specification.

Basically it can be used in endpoints that perform GET communication such as lookup and search processing. Some fields may also be included in the includes field of TwitterResponse.

You can use fields like below:

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(bearerToken: 'YOUR_TOKEN_HERE');

  try {
    final tweets = await twitter.tweetsService.searchRecent(
      query: '#ElonMusk',
      maxResults: 20,
      expansions: v2.TweetExpansion.values,
      tweetFields: [
        v2.TweetField.conversationId,
        v2.TweetField.publicMetrics,
      ],
      userFields: [
        v2.UserField.location,
        v2.UserField.publicMetrics,
      ],
    );

    print(tweets);
  } on v2.TwitterException catch (e) {
    print(e);
  }
}

Note
Some fields must be combined with expansions.

You can see more details about fields from Official Documentation.

1.4.6. OAuth 2.0 Authorization Code Flow with PKCE

Twitter API v2.0 supports authentication methods with OAuth 2.0 PKCE, and it allows users of apps using Twitter API v2.0 to request authorization for the minimum necessary scope of operation.

Since OAuth2.0 PKCE authentication requires going through a browser, twitter_api_v2 does not provide this specification for compatibility with CLI applications. Instead, we provide twitter_oauth2_pkce, a library for Flutter apps.

The twitter_oauth2_pkce is 100% compatible with twitter_api_v2 and can be used. You can see more details from links below.

Also, please refer to the next simple sample Flutter application that combines twitter_api_v2 and twitter_oauth2_pkce.

1.4.7. Change the Timeout Duration

The library specifies a default timeout of 10 seconds for all API communications.

However, there may be times when you wish to specify an arbitrary timeout duration. If there is such a demand, an arbitrary timeout duration can be specified as follows.

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() {
 final twitter = v2.TwitterApi(
    bearerToken: 'YOUR_TOKEN_HERE',

    //! The default timeout is 10 seconds.
    timeout: Duration(seconds: 5),
  );
}

1.4.8. Retry When a Timeout Occurs

Due to the nature of this library's communication with external systems, timeouts may occur due to inevitable communication failures or temporary crashes of the server to which requests are sent.

When such timeouts occur, an effective countermeasure in many cases is to send the request again after a certain interval. And twitter_api_v2 provides an automatic retry feature as a solution to this problem.

There are 3 retry methods provided by twitter_api_v2.

Retry Strategy Constructor Description
Regular Intervals RetryConfig.regularIntervals Retry at regular intervals.
Exponential Backoff RetryConfig.exponentialBackOff The retry interval is increased exponentially according to the number of retries.
Exponential Backoff and Jitter RetryConfig.exponentialBackOffAndJitter A random number called Jitter is added to increase the retry interval exponentially according to the number of retries.

1.4.8.1. Regular Intervals

It would be easy to imagine retries at regular intervals. For example, if a timeout occurs and the request is assumed to be retried 3 times, waiting for 5 seconds and then sending the request again, it can be defined as follows.

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(
    bearerToken: 'YOUR_TOKEN_HERE',

    //! Add these lines.
    retryConfig: v2.RetryConfig.regularIntervals(
      maxAttempts: 3,
      intervalInSeconds: 5,
    ),
  );
}

1.4.8.2. Exponential Backoff

Although retries can be effective by simply performing them at regular intervals as in the above example, sending a large number of requests at regular intervals when the server to which the request is being sent is experiencing a failure is something that should be avoided. Even if the network or server is already down, the retry process can further aggravate the situation by adding to the load.

The solution to these problems is to increase the interval exponentially for each retry. This is an algorithm called Exponential Backoff and twitter_api_v2 supports a specification that allows easy use of this algorithm.

The Exponential Backoff algorithm can be applied on retries by defining RetryConfig as follows.

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(
    bearerToken: 'YOUR_TOKEN_HERE',

    //! Add these lines.
    retryConfig: v2.RetryConfig.exponentialBackOff(
      maxAttempts: 3,
    ),
  );
}

In the above implementation, the interval increases exponentially for each retry count. It can be expressed by next formula.

2 ^ retryCount

1.4.8.3. Exponential Backoff and Jitter

Although the algorithm introduced earlier that exponentially increases the retry interval is already powerful, some may believe that it is not yet sufficient to distribute the sensation of retries. It's more distributed than equally spaced retries, but retries still occur at static intervals.

This problem can be solved by adding a random number called Jitter, and this method is called the Exponential Backoff and Jitter algorithm. By adding a random number to the exponentially increasing retry interval, the retry interval can be distributed more flexibly.

Similar to the previous example, twitter_api_v2 can be implemented as follows.

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(
    bearerToken: 'YOUR_TOKEN_HERE',

    //! Add these lines.
    retryConfig: v2.RetryConfig.exponentialBackOffAndJitter(
      maxAttempts: 3,
    ),
  );
}

In the above implementation, the interval increases exponentially for each retry count with jitter. It can be expressed by next formula.

(2 ^ retryCount) + jitter(Random Number between 0 ~ 3)

1.4.8.4. Do Something on Retry

It would be useful to output logging on retries and a popup notifying the user that a retry has been executed. So twitter_api_v2 provides callbacks that can perform arbitrary processing when retries are executed.

It can be implemented as follows.

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(
    bearerToken: 'YOUR_TOKEN_HERE',
    retryConfig: v2.RetryConfig.regularIntervals(
      maxAttempts: 3,
      intervalInSeconds: 5,

      //! Add this line.
      onExecute: (event) => print('Retrying... ${event.retryCount} times.'),
    ),
  );
}

The RetryEvent passed to the callback contains information on retries.

1.4.9. Thrown Exceptions

twitter_api_v2 provides a convenient exception object for easy handling of exceptional responses and errors returned from Twitter API v2.0.

Exception Description
TwitterException The most basic exception object. For example, it can be used to search for tweets that have already been deleted, etc.
UnauthorizedException Thrown when authentication fails with the specified access token.
RateLimitExceededException Thrown when the request rate limit is exceeded.

1.5. Contribution πŸ†

If you would like to contribute to twitter_api_v2, please create an issue or create a Pull Request.

There are many ways to contribute to the OSS. For example, the following subjects can be considered:

  • There are request parameters or response fields that are not implemented.
  • Documentation is outdated or incomplete.
  • Have a better way or idea to achieve the functionality.
  • etc...

You can see more details from resources below:

Or you can create a discussion if you like.

Feel free to join this development, diverse opinions make software better!

1.6. Contributors ✨

Thanks goes to these wonderful people (emoji key):


Kato Shinya / εŠ θ—€ 真也

πŸ’» πŸ–‹ πŸ”£ πŸ“– 🎨 πŸ’‘ πŸ” πŸ€” πŸš‡ 🚧 πŸ§‘β€πŸ« πŸ“† πŸ’¬ πŸ‘€ πŸ›‘οΈ 🌍 ⚠️ βœ…

Andy Piper

πŸ–‹ πŸ“’

Konstantin

πŸ’» 🎨 πŸ“– πŸ’‘ ⚠️

Roberto Doering

πŸ’» 🎨 πŸ“– πŸ’‘ ⚠️ πŸ€”

Nitesh Sharma

πŸ’» 🎨 πŸ“– πŸ’‘ ⚠️ πŸ€”

ngoluuduythai

πŸ“– 🌍

Abdullah Al Mahmud

πŸ“– 🌍

Oumar fall

πŸ“– 🌍

Natalie Stroud

πŸ“– 🌍

novas1r1

πŸ“– 🌍 πŸ€”

Ikko Ashimine

πŸ“–

This project follows the all-contributors specification. Contributions of any kind welcome!

1.7. Support ❀️

The simplest way to show us your support is by giving the project a star at GitHub and Pub.dev.

You can also support this project by becoming a sponsor on GitHub:

myconsciousness

You can also show on your repository that your app is made with twitter_api_v2 by using one of the following badges:

Powered by twitter_api_v2 Powered by twitter_api_v2 Powered by twitter_api_v2

[![Powered by twitter_api_v2](https://img.shields.io/badge/Powered%20by-twitter_api_v2-00acee.svg)](https://github.com/twitter-dart/twitter-api-v2)
[![Powered by twitter_api_v2](https://img.shields.io/badge/Powered%20by-twitter_api_v2-00acee.svg?style=flat-square)](https://github.com/twitter-dart/twitter-api-v2)
[![Powered by twitter_api_v2](https://img.shields.io/badge/Powered%20by-twitter_api_v2-00acee.svg?style=for-the-badge)](https://github.com/twitter-dart/twitter-api-v2)

1.8. License πŸ”‘

All resources of twitter_api_v2 is provided under the BSD-3 license.

FOSSA Status

Note
License notices in the source are strictly validated based on .github/header-checker-lint.yml. Please check header-checker-lint.yml for the permitted standards.

1.9. More Information 🧐

twitter_api_v2 was designed and implemented by Kato Shinya (@myConsciousness).

Libraries

twitter_api_v2