Interested in learning more about how the Activity Streams data format maps to the X API v2 format?
Check out our comparison guide: Activity Streams compared to X API v2
Please note: It is highly recommended to use the Enriched Native format for enterprise data APIs.
The Enriched Native format includes all new metadata since 2017, such as poll metadata, and additional metrics such as reply_count and quote_count.
Activity Streams format has not been updated with new metadata or enrichments since the character update in 2017.
Activity Object
Activity Streams is an object schema translation of X's original data format created by Gnip to 'normalize the format' of Post data and other social media data using the third party Activity Base Schema described here. Posts are normalized into the activity streams schema, including: note, person, place and service object types as nested objects. Posts can have other nested Post activity obejcts for Retweets, or others including twitter_quoted_status, long_object.
The base level object type "activity" is similar to the Post base level object of the native enriched format. Example payloads in activity streams format can be found here.
Data Dictionary
Below you will find the data dictionary for these ‘root-level’ "activity" attributes, as well as links to child object data dictionaries.
Attribute | Type | Description |
id | string | A unique IRI for the post. In more detail, "tag" is the scheme, "search.x.com" represents the domain for the scheme, and 2005 is when the scheme was derived. When storing Posts, this should be used as the unique identifier or primary key. "id": "tag:search.x.com,2005:1050118621198921728" |
objectType | string | Type of object, always set to "activity" "objectType": "activity" |
object | object | An object representing post being posted or shared. For Retweets, this will contain an entire "activity", with the pertinent fields described in this schema. For Original posts, this will contain a "note" object, with the fields described here. "object": "object": { "objectType": "note", "id": "object:search.x.com,2005:1050118621198921728", "summary": "To make room for more expression, we will now count all emojis as equal—including those with gender and skin t… https://t.co/MkGjXf9aXm", "link": "http://twitter.com/TwitterAPI/statuses/1050118621198921728", "postedTime": "2018-10-10T20:19:24.000Z" } |
long_object | object | An object representing the full text body if the post text extends beyond 140 characters. "long_object": { "body": "To make room for more expression, we will now count all emojis as equal—including those with gender and skin tone modifiers 👍🏻👍🏽👍🏿. This is now reflected in Twitter-Text, our Open Source library. \n\nUsing Twitter-Text? See the forum post for detail: https://t.co/Nx1XZmRCXA", "display_text_range": [ 0, 277 ], "twitter_entities": { "hashtags": [], "urls": [ { "url": "https://t.co/Nx1XZmRCXA", "expanded_url": "https://twittercommunity.com/t/new-update-to-the-twitter-text-library-emoji-character-count/114607", "display_url": "twittercommunity.com/t/new-update-t…", "indices": [ 254, 277 ] } ], "user_mentions": [], "symbols": [] } } |
display_text_range | array | if the post text extends beyond 140 characters. "display_text_range": [ 0, 142 ] |
verb | string | The type of action being taken by the user. Posts, "post" Retweets, "share" Deleted Posts, "delete" The verb is the proper way to distinguish between a Tweet and a true Retweet. However, this only applies to true retweets, and not modified or quoted Tweets, which don't use X Retweet functionality. For a description of AS verbs click here. For Deletes, note that only a limited number of fields will be included, as shown in the sample payload below. "verb": "post" |
postedTime | date (ISO 8601) | The time the action occurred, e.g. the time the post was posted. "postedTime": "2018-10-10T20:19:24.000Z" |
generator | object | An object representing the utility used to post the post. This will contain the name ("displayName") and a link ("link") for the source application generating the Post. "generator": { "displayName": "Twitter Web Client", "link": "http://twitter.com" } |
provider | object | A JSON object representing the provider of the activity. This will contain an objectType ("service"), the name of the provider ("displayName"), and a link to the provider's website ("link"). "provider": { "objectType": "service", "displayName": "Twitter", "link": "http://www.twitter.com" } |
link | string | A Permalink for the post. "link": "http://twitter.com/TwitterAPI/statuses/1050118621198921728" |
body | string | The post text. In Retweets, note that X modifies the value of the body at the root level by adding "RT @username" at the beginning, and by truncating the original text and adding an ellipsis at the end. Thus, for Retweets, your app should look at the object.body to ensure that it is extracting the non-modified text of the original Post (being retweeted). "body": "With Cardiff, Crystal Palace, and Hull City joining the EPL from the Championship it will be a great relegation battle at the end." |
display_text_range | array | Describes the range of characters within the body text that indicates the displayed Post. Posts with leading @mentions will start at more than 0 and Posts with attached media or that extened beyond 140 characters will indicate the display_text_range in the long_object. "display_text_range": [ 14, 42 ] or "long_object": { "display_text_range": [ 0, 277 ]... |
actor | object | An object representing the x user who posted. The Actor Object refers to a X User, and contains all metadata relevant to that user. See actor object details |
inReplyTo | object | A JSON object referring to the Post being replied to, if applicable. Contains a link to the Post. "inReplyTo": { "link": "http:\/\/twitter.com\/GOP\/statuses\/349573991561838593" } |
location | object | A JSON object representing the X "Place" where the post was created. This is an object passed through from the X platform. See location object |
twitter_entities | object | The entities object from X's data format which contains lists of urls, mentions and hashtags. Please reference the X documentation on Entities here Note that in Retweets, X may truncate the values of entities that it extracts at the root level. So, for Retweets, your app should look at object.twitter_entities to ensure that you are using non-truncated values. See twitter_entities object details |
twitter_extended_entities | object | An object from X's native data format containing "media". This will be present for any post where the twitter_entities object has data present in the "media" field, and will include multiple photos where present in the post. Note that this is the correct location to retrieve media information for multi-photo posts. Multiple photos are represented by comma-separated JSON objects within the "media" array. See twitter_extended_entities object details |
gnip | object | An object added to the activity payload to indicate the matching rules, and added enriched data based on enrichments active on the stream or product. See gnip object details |
edit_history | Object | Unique identifiers indicating all versions of a Post. For Posts with no edits, there will be one ID. For Posts with an edit history, there will be multiple IDs, arranged in ascending order reflecting the order of edits, with the most recent version in the last position of the array. The Post IDs can be used to hydrate and view previous versions of a Post.
Example:
edit_history": {
"initial_tweet_id": "1283764123"
"edit_tweet_ids": ["1283764123", "1394263866"]
}
|
edit_controls | Object | When present, indicates how long a Post is still editable for and the number of remaining edits. Posts are only editable for the first 30 minutes after creation and can be edited up to five times. The Post IDs can be used to hydrate and view previous versions of a Post.
Example:
"edit_controls": {
"editable_until_ms": 123
"edits_remaining": 3
}
|
editable | Boolean | When present, indicates if a Post was eligible for edit when published. This field is not dynamic and won't toggle from True to False when a Post reaches its editable time limit, or maximum number of edits. The following Post features will cause this field to be false:
|
Additional Post attributes
Attribute | Type | Description |
---|---|---|
twitter_lang | string | |
favoritesCount | int | Nullable. Indicates approximately how many times this Post has been liked by X users. "favoritesCount":298 |
retweetCount |
int | Number of times this Post has been retweeted. Example: "retweetCount":153 |
Deprecated Attributes
Field | Type | Description |
---|---|---|
geo | object | Point location where the Post was created. |
twitter_filter_level | string | Deprecated field left in for non breaking change |
Nested Post activity obejcts
In several cases, a Post object will included other nested Posts. If you are working with nested objects, then that JSON payload will contain multiple objects, and each Post object may contain its own objects. The root-level object will contain information on the type of action taken, i.e. whether it is a Retweet or a Quote Tweet, and may also contain an object that describes the 'original' Post being shared. Extended Posts will include a nested extended object that extends beyond 140 characters, which was used to prevent breaking changes when the update was made in 2017. Each nested object dictionary is described below.
{
"id": "tag:search.twitter.com,2005:222222222222",
"objectType": "activity",
"verb": "share",
"body": "RT @TheOriginalTweeter: Coffee and art ☕️",
"actor": {
"displayName": "TheRetweeter"
},
"object": {
"id": "tag:search.twitter.com,2005:11111111111",
"objectType": "activity",
"verb": "post",
"body": "Coffee and art ☕️",
"actor": {
"displayName": "TheOriginalTweeter"
},
"object": {
"objectType": "note",
"id": "object:search.twitter.com,2005:11111111111",
"summary": "Coffee and art ☕️",
"link": "http://twitter.com/originaltweeter/statuses/11111111111",
"postedTime": "2020-12-04T11:00:01.000Z"
},
"twitter_entities": {},
"twitter_extended_entities": {}
},
"twitter_entities": {},
"twitter_extended_entities": {},
"gnip": {}
}
{
"id": "tag:search.twitter.com,2005:222222222222",
"objectType": "activity",
"verb": "post",
"body": "Quoting a Tweet: https://t.co/mxiFJ59FlB",
"actor": {
"displayName": "TheQuoter2"
},
"object": {
"objectType": "note",
"id": "object:search.twitter.com,2005:111111111",
"summary": "https://t.co/mxiFJ59FlB"
},
"twitter_entities": {},
"twitter_extended_entities": {},
"gnip": {},
"twitter_quoted_status": {
"id": "tag:search.twitter.com,2005:111111111",
"objectType": "activity",
"verb": "post",
"body": "console.log('Happy birthday, JavaScript!');",
"actor": {
"displayName": "TheOriginalTweeter"
},
"object": {
"objectType": "note",
"id": "object:search.twitter.com,2005:111111111"
},
"twitter_entities": {}
}
}
Retweeted Quote Tweet:
{
"id": "tag:search.twitter.com,2005:1293612267087384577",
"objectType": "activity",
"verb": "share",
"postedTime": "2020-08-12T18:16:13.000Z",
"generator": {},
"provider": {},
"link": "http://twitter.com/TwitterDev/statuses/1293612267087384577",
"body": "RT @compston: So excited to make this first set of endpoints available - many more to come before we're done. The @TwitterDev #DevRel team…",
"actor": {},
"object": {},
"favoritesCount": 0,
"twitter_entities": {},
"twitter_lang": "en",
"retweetCount": 13,
"gnip": {},
"twitter_filter_level": "low",
"twitter_quoted_status": {}
}
{
"id": "tag:search.twitter.com,2005:1050118621198921728",
"objectType": "activity",
"verb": "post",
"postedTime": "2018-10-10T20:19:24.000Z",
"generator": {
"displayName": "Twitter Web Client",
"link": "http://twitter.com"
},
"provider": {
"objectType": "service",
"displayName": "Twitter",
"link": "http://www.twitter.com"
},
"link": "http://twitter.com/TwitterAPI/statuses/1050118621198921728",
"body": "To make room for more expression, we will now count all emojis as equal—including those with gender and skin t… https://t.co/MkGjXf9aXm",
"long_object": {
"body": "To make room for more expression, we will now count all emojis as equal—including those with gender and skin tone modifiers 👍🏻👍🏽👍🏿. This is now reflected in Twitter-Text, our Open Source library. \n\nUsing Twitter-Text? See the forum post for detail: https://t.co/Nx1XZmRCXA",
"display_text_range": [
0,
277
],
"twitter_entities": {see twitter_entities object},
"actor": {see actor object},
"object": {
"objectType": "note",
"id": "object:search.twitter.com,2005:1050118621198921728",
"summary": "To make room for more expression, we will now count all emojis as equal—including those with gender and skin t… https://t.co/MkGjXf9aXm",
"link": "http://twitter.com/TwitterAPI/statuses/1050118621198921728",
"postedTime": "2018-10-10T20:19:24.000Z"
},
"favoritesCount": 298,
"twitter_entities": {see twitter_entities object},
"twitter_lang": "en",
"retweetCount": 153,
"gnip": {see gnip object},
"twitter_filter_level": "low"
}
Next Steps
Explore the other nested objects of this format:
- Review actor object
- Review location object
- Review twitter_entities object
- See migration guide from Activity Streams to X API v2 format