<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[GetXAPI]]></title><description><![CDATA[GetXAPI]]></description><link>https://twitter-api.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6a9d692f5b023c01fe97fa26/46fbd393-1c82-4a2c-86ae-bbc877b99493.png</url><title>GetXAPI</title><link>https://twitter-api.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 07 Sep 2026 22:12:53 GMT</lastBuildDate><atom:link href="https://twitter-api.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[X (Twitter) API Object Reference: Tweet and User Fields]]></title><description><![CDATA[Every response from the X API v2 is built from a small set of objects: the Post (still called a Tweet in most field names), the User, and the Media, Poll and Place objects that hang off them. This ref]]></description><link>https://twitter-api.hashnode.dev/x-twitter-api-object-reference-tweet-and-user-fields</link><guid isPermaLink="true">https://twitter-api.hashnode.dev/x-twitter-api-object-reference-tweet-and-user-fields</guid><category><![CDATA[Twitter]]></category><category><![CDATA[#TwitterAPI ]]></category><category><![CDATA[APIs]]></category><category><![CDATA[json]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Bozad from GetXAPI]]></dc:creator><pubDate>Sun, 06 Sep 2026 13:51:29 GMT</pubDate><content:encoded><![CDATA[<p>Every response from the X API v2 is built from a small set of objects: the Post (still called a Tweet in most field names), the User, and the Media, Poll and Place objects that hang off them. This reference lists every field on each, with its type, what it actually contains, the authentication it needs, and the nested keys and enum values that the official one-line descriptions leave out.</p>
<p>Field names, types and descriptions are taken from <a href="https://docs.x.com/x-api/fundamentals/data-dictionary">X's own v2 data dictionary</a>, the <a href="https://docs.x.com/x-api/fundamentals/fields">fields guide</a> and the <a href="https://docs.x.com/x-api/fundamentals/expansions">expansions guide</a>, read on 30 August 2026.</p>
<blockquote>
<p><strong>TL;DR:</strong> A post lookup returns only <code>id</code>, <code>text</code> and <code>edit_history_tweet_ids</code> unless you ask for more with <code>tweet.fields</code>. Ids are strings, not numbers, on purpose. <code>public_metrics</code> is readable with app-only auth; the <code>non_public_metrics</code>, <code>organic_metrics</code> and <code>promoted_metrics</code> objects need user context and only work on the authenticated user's own posts. Related objects such as the author or attached media are never nested inside a post; they arrive in a separate <code>includes</code> block that you join on id.</p>
</blockquote>
<h2>What Is the X API Tweet Object?</h2>
<p>The X API tweet object, called a Post in X's current vocabulary, is the JSON record v2 returns for a single post. By default it carries three fields. Up to 29 top-level fields are available on request, several of them objects with their own keys, and it links to the author, referenced posts, media, polls and places by id rather than embedding them.</p>
<h2>How Fields Work</h2>
<p>The v2 API returns a minimal object by default and expects you to opt in to everything else. Each object type has its own query parameter:</p>
<table>
<thead>
<tr>
<th>Object</th>
<th>Parameter</th>
<th>Default fields</th>
</tr>
</thead>
<tbody><tr>
<td>Post</td>
<td><code>tweet.fields</code></td>
<td><code>id</code>, <code>text</code>, <code>edit_history_tweet_ids</code></td>
</tr>
<tr>
<td>User</td>
<td><code>user.fields</code></td>
<td><code>id</code>, <code>name</code>, <code>username</code></td>
</tr>
<tr>
<td>Media</td>
<td><code>media.fields</code></td>
<td><code>media_key</code>, <code>type</code></td>
</tr>
<tr>
<td>Poll</td>
<td><code>poll.fields</code></td>
<td><code>id</code>, <code>options</code></td>
</tr>
<tr>
<td>Place</td>
<td><code>place.fields</code></td>
<td><code>id</code>, <code>full_name</code></td>
</tr>
</tbody></table>
<p>A request for a post with engagement counts and a timestamp therefore looks like <code>?tweet.fields=created_at,public_metrics,author_id</code>. Omit the parameter and those keys are simply absent from the response, which is the single most common cause of "the API is not returning X" questions.</p>
<p><img src="https://www.getxapi.com/blog/content/images/x-twitter-api-object-reference-default-fields.webp" alt="Post lookup returning only the default id, text and edit history fields until tweet.fields is requested" /></p>
<h2>Post (Tweet) Object Fields</h2>
<p>Auth column: <strong>app</strong> means readable with an app-only bearer token; <strong>user</strong> means the request needs user-context OAuth, and for the three private metric objects, the authenticated user must be the post's author.</p>
<table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Auth</th>
<th>What it holds</th>
</tr>
</thead>
<tbody><tr>
<td><code>id</code></td>
<td>string</td>
<td>app</td>
<td>Unique post id, serialised as a string. Default field</td>
</tr>
<tr>
<td><code>text</code></td>
<td>string</td>
<td>app</td>
<td>UTF-8 text. Truncated at 280 characters for long posts; see <code>note_tweet</code>. Default field</td>
</tr>
<tr>
<td><code>edit_history_tweet_ids</code></td>
<td>array of strings</td>
<td>app</td>
<td>Every version id of an edited post. One element when never edited. Default field</td>
</tr>
<tr>
<td><code>author_id</code></td>
<td>string</td>
<td>app</td>
<td>Id of the posting user. Expand with <code>author_id</code> to get the User object</td>
</tr>
<tr>
<td><code>created_at</code></td>
<td>string, ISO 8601</td>
<td>app</td>
<td>Creation time in UTC with millisecond precision, e.g. <code>2024-01-15T12:00:00.000Z</code></td>
</tr>
<tr>
<td><code>conversation_id</code></td>
<td>string</td>
<td>app</td>
<td>Id of the root post of the thread this post belongs to</td>
</tr>
<tr>
<td><code>in_reply_to_user_id</code></td>
<td>string</td>
<td>app</td>
<td>Id of the user being replied to, present only on replies</td>
</tr>
<tr>
<td><code>referenced_tweets</code></td>
<td>array of objects</td>
<td>app</td>
<td>Posts this post retweets, quotes or replies to. See nested keys below</td>
</tr>
<tr>
<td><code>public_metrics</code></td>
<td>object</td>
<td>app</td>
<td>Six public counters. See nested keys below</td>
</tr>
<tr>
<td><code>non_public_metrics</code></td>
<td>object</td>
<td>user, own posts</td>
<td><code>impression_count</code>, <code>user_profile_clicks</code>, <code>url_link_clicks</code>, <code>engagements</code></td>
</tr>
<tr>
<td><code>organic_metrics</code></td>
<td>object</td>
<td>user, own posts</td>
<td>The engagement counters, restricted to organic delivery</td>
</tr>
<tr>
<td><code>promoted_metrics</code></td>
<td>object</td>
<td>user, own posts</td>
<td>The engagement counters, restricted to promoted delivery</td>
</tr>
<tr>
<td><code>entities</code></td>
<td>object</td>
<td>app</td>
<td>Hashtags, mentions, URLs, cashtags and annotations parsed from <code>text</code>. See nested keys below</td>
</tr>
<tr>
<td><code>attachments</code></td>
<td>object</td>
<td>app</td>
<td><code>media_keys</code> and <code>poll_ids</code> for attached media and polls</td>
</tr>
<tr>
<td><code>geo</code></td>
<td>object</td>
<td>app</td>
<td><code>place_id</code>, and <code>coordinates</code> when the post carries an exact point</td>
</tr>
<tr>
<td><code>context_annotations</code></td>
<td>array of objects</td>
<td>app</td>
<td>Domain and entity pairs X has inferred for the post, for topical classification</td>
</tr>
<tr>
<td><code>lang</code></td>
<td>string</td>
<td>app</td>
<td>BCP 47 language code detected by X, or <code>und</code> when undetermined</td>
</tr>
<tr>
<td><code>possibly_sensitive</code></td>
<td>boolean</td>
<td>app</td>
<td>Whether X flags the content as potentially sensitive</td>
</tr>
<tr>
<td><code>reply_settings</code></td>
<td>string</td>
<td>app</td>
<td>Who may reply: <code>everyone</code>, <code>mentioned_users</code> or <code>followers</code></td>
</tr>
<tr>
<td><code>edit_controls</code></td>
<td>object</td>
<td>app</td>
<td><code>edits_remaining</code>, <code>is_edit_eligible</code>, <code>editable_until</code></td>
</tr>
<tr>
<td><code>note_tweet</code></td>
<td>object</td>
<td>app</td>
<td>Full <code>text</code> and <code>entities</code> for posts over 280 characters</td>
</tr>
<tr>
<td><code>display_text_range</code></td>
<td>array of two integers</td>
<td>app</td>
<td>Start and end index of the portion of <code>text</code> shown by default</td>
</tr>
<tr>
<td><code>withheld</code></td>
<td>object</td>
<td>app</td>
<td><code>copyright</code>, <code>country_codes</code>, <code>scope</code> for content withheld in some countries</td>
</tr>
<tr>
<td><code>article</code></td>
<td>object</td>
<td>app</td>
<td>Metadata for an X Article embedded in the post</td>
</tr>
<tr>
<td><code>card_uri</code></td>
<td>string</td>
<td>app</td>
<td>URI of the link preview card, when present</td>
</tr>
<tr>
<td><code>community_id</code></td>
<td>string</td>
<td>app</td>
<td>Id of the Community the post was published to</td>
</tr>
<tr>
<td><code>media_metadata</code></td>
<td>array of objects</td>
<td>app</td>
<td>Per-attachment metadata such as <code>alt_text</code></td>
</tr>
<tr>
<td><code>paid_partnership</code></td>
<td>boolean</td>
<td>app</td>
<td>Whether the author disclosed the post as a paid partnership</td>
</tr>
<tr>
<td><code>scopes</code></td>
<td>object</td>
<td>app</td>
<td>Audience scope details. Returned only for promoted posts</td>
</tr>
</tbody></table>
<h3>Nested keys inside public_metrics and the private metric objects</h3>
<table>
<thead>
<tr>
<th>Object</th>
<th>Key</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td><code>public_metrics</code></td>
<td><code>retweet_count</code></td>
<td>Reposts, excluding quotes</td>
</tr>
<tr>
<td><code>public_metrics</code></td>
<td><code>reply_count</code></td>
<td>Direct replies</td>
</tr>
<tr>
<td><code>public_metrics</code></td>
<td><code>like_count</code></td>
<td>Likes</td>
</tr>
<tr>
<td><code>public_metrics</code></td>
<td><code>quote_count</code></td>
<td>Quote posts</td>
</tr>
<tr>
<td><code>public_metrics</code></td>
<td><code>bookmark_count</code></td>
<td>Bookmarks</td>
</tr>
<tr>
<td><code>public_metrics</code></td>
<td><code>impression_count</code></td>
<td>Views, the public count shown under the post</td>
</tr>
<tr>
<td><code>non_public_metrics</code></td>
<td><code>impression_count</code></td>
<td>Impressions as measured for the author</td>
</tr>
<tr>
<td><code>non_public_metrics</code></td>
<td><code>user_profile_clicks</code></td>
<td>Clicks through to the author's profile</td>
</tr>
<tr>
<td><code>non_public_metrics</code></td>
<td><code>url_link_clicks</code></td>
<td>Clicks on links in the post</td>
</tr>
<tr>
<td><code>non_public_metrics</code></td>
<td><code>engagements</code></td>
<td>Total engagements of every type</td>
</tr>
</tbody></table>
<p>All metric values are captured <strong>at the time of the request</strong>. They are not monotonic and not live: two reads seconds apart can differ, and a stored count from last week is not corrected by reading again.</p>
<h3>Nested keys inside entities, referenced_tweets, attachments and geo</h3>
<table>
<thead>
<tr>
<th>Parent</th>
<th>Key</th>
<th>Type</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td><code>entities</code></td>
<td><code>hashtags</code></td>
<td>array</td>
<td>Each with <code>start</code>, <code>end</code>, <code>tag</code></td>
</tr>
<tr>
<td><code>entities</code></td>
<td><code>mentions</code></td>
<td>array</td>
<td>Each with <code>start</code>, <code>end</code>, <code>username</code>, <code>id</code></td>
</tr>
<tr>
<td><code>entities</code></td>
<td><code>urls</code></td>
<td>array</td>
<td>Each with <code>start</code>, <code>end</code>, <code>url</code> (t.co), <code>expanded_url</code>, <code>display_url</code>, and <code>unwound_url</code> where X resolved a further redirect</td>
</tr>
<tr>
<td><code>entities</code></td>
<td><code>cashtags</code></td>
<td>array</td>
<td>Each with <code>start</code>, <code>end</code>, <code>tag</code></td>
</tr>
<tr>
<td><code>entities</code></td>
<td><code>annotations</code></td>
<td>array</td>
<td>Each with <code>start</code>, <code>end</code>, <code>probability</code>, <code>type</code>, <code>normalized_text</code></td>
</tr>
<tr>
<td><code>referenced_tweets[]</code></td>
<td><code>type</code></td>
<td>string</td>
<td><code>retweeted</code>, <code>quoted</code> or <code>replied_to</code></td>
</tr>
<tr>
<td><code>referenced_tweets[]</code></td>
<td><code>id</code></td>
<td>string</td>
<td>Id of the referenced post</td>
</tr>
<tr>
<td><code>attachments</code></td>
<td><code>media_keys</code></td>
<td>array of strings</td>
<td>Keys that match <code>includes.media[].media_key</code></td>
</tr>
<tr>
<td><code>attachments</code></td>
<td><code>poll_ids</code></td>
<td>array of strings</td>
<td>Ids that match <code>includes.polls[].id</code></td>
</tr>
<tr>
<td><code>geo</code></td>
<td><code>place_id</code></td>
<td>string</td>
<td>Id that matches <code>includes.places[].id</code></td>
</tr>
<tr>
<td><code>geo</code></td>
<td><code>coordinates</code></td>
<td>object</td>
<td>GeoJSON <code>Point</code> with <code>[longitude, latitude]</code>, only when the author tagged an exact location</td>
</tr>
<tr>
<td><code>edit_controls</code></td>
<td><code>edits_remaining</code></td>
<td>integer</td>
<td>Edits still allowed</td>
</tr>
<tr>
<td><code>edit_controls</code></td>
<td><code>is_edit_eligible</code></td>
<td>boolean</td>
<td>Whether the post can still be edited at all</td>
</tr>
<tr>
<td><code>edit_controls</code></td>
<td><code>editable_until</code></td>
<td>string, ISO 8601</td>
<td>Deadline after which no edits are accepted</td>
</tr>
<tr>
<td><code>withheld</code></td>
<td><code>copyright</code></td>
<td>boolean</td>
<td>Withheld for a copyright complaint</td>
</tr>
<tr>
<td><code>withheld</code></td>
<td><code>country_codes</code></td>
<td>array of strings</td>
<td>ISO 3166-1 alpha-2 codes where it is withheld</td>
</tr>
<tr>
<td><code>withheld</code></td>
<td><code>scope</code></td>
<td>string</td>
<td><code>tweet</code> or <code>user</code></td>
</tr>
</tbody></table>
<p><code>entities.urls[].url</code> is always the <code>t.co</code> wrapper. The address a human would recognise is <code>expanded_url</code>, and if X followed a further redirect, <code>unwound_url</code>. Code that indexes links by <code>url</code> ends up with a table of <code>t.co</code> strings.</p>
<h2>User Object Fields</h2>
<table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Auth</th>
<th>What it holds</th>
</tr>
</thead>
<tbody><tr>
<td><code>id</code></td>
<td>string</td>
<td>app</td>
<td>Unique user id, serialised as a string. Default field</td>
</tr>
<tr>
<td><code>name</code></td>
<td>string</td>
<td>app</td>
<td>Display name as set on the profile. Not necessarily a person's name. Default field</td>
</tr>
<tr>
<td><code>username</code></td>
<td>string</td>
<td>app</td>
<td>The handle without the <code>@</code>. Default field</td>
</tr>
<tr>
<td><code>created_at</code></td>
<td>string, ISO 8601</td>
<td>app</td>
<td>UTC account creation time</td>
</tr>
<tr>
<td><code>description</code></td>
<td>string</td>
<td>app</td>
<td>Profile bio, empty string when unset</td>
</tr>
<tr>
<td><code>entities</code></td>
<td>object</td>
<td>app</td>
<td>Nested <code>url</code> and <code>description</code> objects, each with <code>urls</code>, <code>hashtags</code>, <code>mentions</code> and <code>cashtags</code> arrays</td>
</tr>
<tr>
<td><code>location</code></td>
<td>string</td>
<td>app</td>
<td>Free-text profile location. Not validated, not geocoded</td>
</tr>
<tr>
<td><code>url</code></td>
<td>string</td>
<td>app</td>
<td>Profile website as a <code>t.co</code> link. The real address is in <code>entities.url.urls[].expanded_url</code></td>
</tr>
<tr>
<td><code>profile_image_url</code></td>
<td>string</td>
<td>app</td>
<td>Avatar URL as shown on the profile</td>
</tr>
<tr>
<td><code>profile_banner_url</code></td>
<td>string</td>
<td>app</td>
<td>Header image URL</td>
</tr>
<tr>
<td><code>pinned_tweet_id</code></td>
<td>string</td>
<td>app</td>
<td>Id of the pinned post. Expand with <code>pinned_tweet_id</code></td>
</tr>
<tr>
<td><code>most_recent_tweet_id</code></td>
<td>string</td>
<td>app</td>
<td>Id of the user's latest post</td>
</tr>
<tr>
<td><code>protected</code></td>
<td>boolean</td>
<td>app</td>
<td>Whether posts are visible only to approved followers</td>
</tr>
<tr>
<td><code>public_metrics</code></td>
<td>object</td>
<td>app</td>
<td><code>followers_count</code>, <code>following_count</code>, <code>tweet_count</code>, <code>listed_count</code></td>
</tr>
<tr>
<td><code>verified</code></td>
<td>boolean</td>
<td>app</td>
<td>Whether the account currently carries any checkmark</td>
</tr>
<tr>
<td><code>verified_type</code></td>
<td>string</td>
<td>app</td>
<td><code>blue</code>, <code>business</code> or <code>government</code></td>
</tr>
<tr>
<td><code>verified_followers_count</code></td>
<td>string</td>
<td>app</td>
<td>Number of verified followers, serialised as a string</td>
</tr>
<tr>
<td><code>is_identity_verified</code></td>
<td>boolean</td>
<td>app</td>
<td>Whether the account completed ID verification</td>
</tr>
<tr>
<td><code>parody</code></td>
<td>boolean</td>
<td>app</td>
<td>Whether the account carries the Parody label</td>
</tr>
<tr>
<td><code>affiliation</code></td>
<td>object</td>
<td>app</td>
<td>Details of an affiliate badge, when present</td>
</tr>
<tr>
<td><code>withheld</code></td>
<td>object</td>
<td>app</td>
<td>Same shape as on the post: <code>copyright</code>, <code>country_codes</code>, <code>scope</code></td>
</tr>
<tr>
<td><code>connection_status</code></td>
<td>array of strings</td>
<td>user</td>
<td>Relationship between the authenticated user and this user. See values below</td>
</tr>
<tr>
<td><code>receives_your_dm</code></td>
<td>boolean</td>
<td>user</td>
<td>Whether this user will accept a DM from the authenticated user</td>
</tr>
<tr>
<td><code>subscription</code></td>
<td>object</td>
<td>user</td>
<td>Whether this user subscribes to the authenticated user</td>
</tr>
<tr>
<td><code>subscription_type</code></td>
<td>string</td>
<td>user, self only</td>
<td><code>None</code>, <code>Basic</code>, <code>Premium</code> or <code>PremiumPlus</code>. Always <code>None</code> for any user other than the authenticated one</td>
</tr>
<tr>
<td><code>confirmed_email</code></td>
<td>string</td>
<td>user, self only</td>
<td>Confirmed email of the authenticated user</td>
</tr>
</tbody></table>
<h3>Enum values on the user object</h3>
<table>
<thead>
<tr>
<th>Field</th>
<th>Values</th>
</tr>
</thead>
<tbody><tr>
<td><code>verified_type</code></td>
<td><code>blue</code>, <code>business</code>, <code>government</code></td>
</tr>
<tr>
<td><code>connection_status[]</code></td>
<td><code>following</code>, <code>followed_by</code>, <code>follow_request_sent</code>, <code>follow_request_received</code>, <code>blocking</code>, <code>muting</code></td>
</tr>
<tr>
<td><code>subscription_type</code></td>
<td><code>None</code>, <code>Basic</code>, <code>Premium</code>, <code>PremiumPlus</code></td>
</tr>
</tbody></table>
<h2>Media, Poll and Place Objects</h2>
<p>These never appear at the top level. They arrive in <code>includes.media</code>, <code>includes.polls</code> and <code>includes.places</code> when the matching expansion is requested, and you join them to the post on <code>media_key</code>, poll <code>id</code> or place <code>id</code>.</p>
<h3>Media</h3>
<table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>What it holds</th>
</tr>
</thead>
<tbody><tr>
<td><code>media_key</code></td>
<td>string</td>
<td>Unique key, e.g. <code>13_1263145212760805376</code>. Default field</td>
</tr>
<tr>
<td><code>type</code></td>
<td>string</td>
<td><code>photo</code>, <code>video</code> or <code>animated_gif</code>. Default field</td>
</tr>
<tr>
<td><code>url</code></td>
<td>string</td>
<td>Direct file URL. Returned for photos</td>
</tr>
<tr>
<td><code>preview_image_url</code></td>
<td>string</td>
<td>Static placeholder image for videos and GIFs</td>
</tr>
<tr>
<td><code>variants</code></td>
<td>array of objects</td>
<td>Playback renditions for video and GIF, each with <code>bit_rate</code>, <code>content_type</code> and <code>url</code></td>
</tr>
<tr>
<td><code>duration_ms</code></td>
<td>integer</td>
<td>Video length in milliseconds. Video only</td>
</tr>
<tr>
<td><code>height</code></td>
<td>integer</td>
<td>Pixel height</td>
</tr>
<tr>
<td><code>width</code></td>
<td>integer</td>
<td>Pixel width</td>
</tr>
<tr>
<td><code>alt_text</code></td>
<td>string</td>
<td>Accessibility description, up to 1,000 characters</td>
</tr>
<tr>
<td><code>public_metrics</code></td>
<td>object</td>
<td><code>view_count</code> for video</td>
</tr>
<tr>
<td><code>non_public_metrics</code></td>
<td>object</td>
<td>Quartile playback counts. User context, own posts</td>
</tr>
<tr>
<td><code>organic_metrics</code></td>
<td>object</td>
<td>Playback counts in organic delivery. User context, own posts</td>
</tr>
<tr>
<td><code>promoted_metrics</code></td>
<td>object</td>
<td>Playback counts in promoted delivery. User context, own posts</td>
</tr>
</tbody></table>
<p>A video's downloadable file is never in <code>url</code>. It is one of the entries in <code>variants</code>, usually the highest <code>bit_rate</code> with <code>content_type</code> of <code>video/mp4</code>.</p>
<h3>Poll</h3>
<table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>What it holds</th>
</tr>
</thead>
<tbody><tr>
<td><code>id</code></td>
<td>string</td>
<td>Poll id. Default field</td>
</tr>
<tr>
<td><code>options</code></td>
<td>array of objects</td>
<td>Each with <code>position</code>, <code>label</code>, <code>votes</code>. Default field</td>
</tr>
<tr>
<td><code>duration_minutes</code></td>
<td>integer</td>
<td>Total poll length</td>
</tr>
<tr>
<td><code>end_datetime</code></td>
<td>string, ISO 8601</td>
<td>When voting closes or closed</td>
</tr>
<tr>
<td><code>voting_status</code></td>
<td>string</td>
<td><code>open</code> or <code>closed</code></td>
</tr>
</tbody></table>
<h3>Place</h3>
<table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>What it holds</th>
</tr>
</thead>
<tbody><tr>
<td><code>id</code></td>
<td>string</td>
<td>Place id. Default field</td>
</tr>
<tr>
<td><code>full_name</code></td>
<td>string</td>
<td>Long-form name, e.g. <code>Manhattan, NY</code>. Default field</td>
</tr>
<tr>
<td><code>name</code></td>
<td>string</td>
<td>Short name</td>
</tr>
<tr>
<td><code>place_type</code></td>
<td>string</td>
<td>Granularity such as <code>city</code>, <code>admin</code>, <code>country</code>, <code>poi</code></td>
</tr>
<tr>
<td><code>country</code></td>
<td>string</td>
<td>Full country name</td>
</tr>
<tr>
<td><code>country_code</code></td>
<td>string</td>
<td>ISO 3166-1 alpha-2 code</td>
</tr>
<tr>
<td><code>contained_within</code></td>
<td>array of strings</td>
<td>Ids of larger places that contain this one</td>
</tr>
<tr>
<td><code>geo</code></td>
<td>object</td>
<td>GeoJSON <code>Feature</code> with a <code>bbox</code> bounding box</td>
</tr>
</tbody></table>
<h2>Expansions: Pulling Related Objects Into the Same Response</h2>
<p>An expansion asks X to include the object behind an id field. The post keeps the id; the object lands in <code>includes</code>.</p>
<p><img src="https://www.getxapi.com/blog/content/images/x-twitter-api-object-reference-includes-join.webp" alt="X API post author_id joined manually to the matching user in includes.users" /></p>
<table>
<thead>
<tr>
<th>Expansion</th>
<th>Adds to <code>includes</code></th>
<th>Joins on</th>
</tr>
</thead>
<tbody><tr>
<td><code>author_id</code></td>
<td><code>users</code></td>
<td><code>post.author_id</code> = <code>user.id</code></td>
</tr>
<tr>
<td><code>referenced_tweets.id</code></td>
<td><code>tweets</code></td>
<td><code>post.referenced_tweets[].id</code> = <code>tweet.id</code></td>
</tr>
<tr>
<td><code>referenced_tweets.id.author_id</code></td>
<td><code>users</code></td>
<td>authors of those referenced posts</td>
</tr>
<tr>
<td><code>in_reply_to_user_id</code></td>
<td><code>users</code></td>
<td><code>post.in_reply_to_user_id</code> = <code>user.id</code></td>
</tr>
<tr>
<td><code>attachments.media_keys</code></td>
<td><code>media</code></td>
<td><code>post.attachments.media_keys[]</code> = <code>media.media_key</code></td>
</tr>
<tr>
<td><code>attachments.poll_ids</code></td>
<td><code>polls</code></td>
<td><code>post.attachments.poll_ids[]</code> = <code>poll.id</code></td>
</tr>
<tr>
<td><code>geo.place_id</code></td>
<td><code>places</code></td>
<td><code>post.geo.place_id</code> = <code>place.id</code></td>
</tr>
<tr>
<td><code>entities.mentions.username</code></td>
<td><code>users</code></td>
<td><code>post.entities.mentions[].username</code> = <code>user.username</code></td>
</tr>
<tr>
<td><code>edit_history_tweet_ids</code></td>
<td><code>tweets</code></td>
<td>previous versions of an edited post</td>
</tr>
<tr>
<td><code>pinned_tweet_id</code> (user lookups)</td>
<td><code>tweets</code></td>
<td><code>user.pinned_tweet_id</code> = <code>tweet.id</code></td>
</tr>
</tbody></table>
<p>Expansions and fields compose. <code>expansions=author_id&amp;user.fields=public_metrics</code> returns the author in <code>includes.users</code> <strong>with</strong> follower counts; without the <code>user.fields</code> part the included user carries only <code>id</code>, <code>name</code> and <code>username</code>.</p>
<h2>The Fields Most Code Gets Wrong</h2>
<p><img src="https://www.getxapi.com/blog/content/images/x-twitter-api-object-reference-id-string.webp" alt="Large X API identifiers losing trailing digits when parsed as numbers instead of strings" /></p>
<table>
<thead>
<tr>
<th>Mistake</th>
<th>What actually happens</th>
<th>Fix</th>
</tr>
</thead>
<tbody><tr>
<td>Parsing <code>id</code> as a number</td>
<td>Ids exceed 2^53, so JavaScript and any double-based parser corrupt the low digits silently</td>
<td>Keep ids as strings end to end</td>
</tr>
<tr>
<td>Reading <code>text</code> for long posts</td>
<td><code>text</code> is cut at 280 characters</td>
<td>Prefer <code>note_tweet.text</code> when <code>note_tweet</code> is present</td>
</tr>
<tr>
<td>Treating <code>verified: true</code> as notability</td>
<td>Since paid verification, <code>blue</code> subscribers return <code>verified: true</code></td>
<td>Branch on <code>verified_type</code></td>
</tr>
<tr>
<td>Using <code>entities.urls[].url</code></td>
<td>It is the <code>t.co</code> wrapper, not the destination</td>
<td>Use <code>expanded_url</code>, or <code>unwound_url</code> if present</td>
</tr>
<tr>
<td>Counting <code>retweet_count</code> as reposts plus quotes</td>
<td>Quotes are counted separately in <code>quote_count</code></td>
<td>Sum both if you want total amplification</td>
</tr>
<tr>
<td>Distinguishing a retweet from a quote by <code>text</code></td>
<td>Both carry text; the reliable signal is <code>referenced_tweets[].type</code></td>
<td>Check for <code>retweeted</code> versus <code>quoted</code></td>
</tr>
<tr>
<td>Expecting <code>created_at</code> without asking</td>
<td>It is not a default field</td>
<td>Add <code>created_at</code> to <code>tweet.fields</code></td>
</tr>
<tr>
<td>Storing <code>public_metrics</code> as truth</td>
<td>They are point-in-time and can decrease</td>
<td>Store the request timestamp alongside every count</td>
</tr>
<tr>
<td>Reading <code>user.url</code> as the website</td>
<td>It is a <code>t.co</code> link</td>
<td>Use <code>entities.url.urls[0].expanded_url</code></td>
</tr>
<tr>
<td>Looking for the author inside the post</td>
<td>The User object is never nested</td>
<td>Request <code>expansions=author_id</code> and join on id</td>
</tr>
</tbody></table>
<h2>How These Fields Map on a Managed API</h2>
<p>A managed provider that returns denormalised responses removes the fields-and-expansions step: the author, counts and media arrive inline on every post, with no <code>tweet.fields</code>, <code>expansions</code> or <code>includes</code> join to write. The vocabulary shifts to camelCase, so the mapping is worth having in one place. On GetXAPI, the correspondence for the fields most pipelines depend on is:</p>
<table>
<thead>
<tr>
<th>X API v2 field</th>
<th>GetXAPI field</th>
<th>Note</th>
</tr>
</thead>
<tbody><tr>
<td><code>id</code></td>
<td><code>id</code></td>
<td>String in both</td>
</tr>
<tr>
<td><code>text</code></td>
<td><code>text</code></td>
<td>Full text, no 280 cut</td>
</tr>
<tr>
<td><code>created_at</code></td>
<td><code>createdAt</code></td>
<td></td>
</tr>
<tr>
<td><code>lang</code></td>
<td><code>lang</code></td>
<td></td>
</tr>
<tr>
<td><code>conversation_id</code></td>
<td><code>conversationId</code></td>
<td></td>
</tr>
<tr>
<td><code>in_reply_to_user_id</code></td>
<td><code>inReplyToUserId</code></td>
<td>Plus <code>inReplyToId</code> for the parent post and <code>isReply</code></td>
</tr>
<tr>
<td><code>public_metrics.like_count</code></td>
<td><code>likeCount</code></td>
<td></td>
</tr>
<tr>
<td><code>public_metrics.retweet_count</code></td>
<td><code>retweetCount</code></td>
<td></td>
</tr>
<tr>
<td><code>public_metrics.reply_count</code></td>
<td><code>replyCount</code></td>
<td></td>
</tr>
<tr>
<td><code>public_metrics.quote_count</code></td>
<td><code>quoteCount</code></td>
<td></td>
</tr>
<tr>
<td><code>public_metrics.bookmark_count</code></td>
<td><code>bookmarkCount</code></td>
<td></td>
</tr>
<tr>
<td><code>public_metrics.impression_count</code></td>
<td><code>viewCount</code></td>
<td></td>
</tr>
<tr>
<td><code>author_id</code> + <code>includes.users[]</code></td>
<td><code>author</code></td>
<td>The User object inline, no expansion</td>
</tr>
<tr>
<td><code>referenced_tweets[type=quoted]</code> + <code>includes.tweets[]</code></td>
<td><code>quoted_tweet</code></td>
<td>Inline</td>
</tr>
<tr>
<td><code>attachments.media_keys</code> + <code>includes.media[]</code></td>
<td><code>media</code></td>
<td>Inline</td>
</tr>
<tr>
<td><code>user.username</code></td>
<td><code>userName</code></td>
<td></td>
</tr>
<tr>
<td><code>user.public_metrics.followers_count</code></td>
<td><code>followers</code></td>
<td></td>
</tr>
<tr>
<td><code>user.public_metrics.following_count</code></td>
<td><code>following</code></td>
<td></td>
</tr>
<tr>
<td><code>user.public_metrics.tweet_count</code></td>
<td><code>statusesCount</code></td>
<td></td>
</tr>
<tr>
<td><code>user.verified</code></td>
<td><code>isVerified</code></td>
<td>Legacy checkmark</td>
</tr>
<tr>
<td><code>user.verified_type</code> = <code>blue</code></td>
<td><code>isBlueVerified</code></td>
<td>Boolean rather than enum</td>
</tr>
<tr>
<td><code>user.verified_type</code></td>
<td><code>verifiedType</code></td>
<td></td>
</tr>
<tr>
<td><code>user.profile_image_url</code></td>
<td><code>profilePicture</code></td>
<td></td>
</tr>
<tr>
<td><code>user.profile_banner_url</code></td>
<td><code>coverPicture</code></td>
<td></td>
</tr>
</tbody></table>
<p>The shape is documented per endpoint in the <a href="https://docs.getxapi.com/docs">GetXAPI API reference</a>, for example <a href="https://docs.getxapi.com/docs/tweets/tweet-detail">tweet detail</a> and <a href="https://docs.getxapi.com/docs/users/user-info">user info</a>. Reads are billed per call at $0.001, with a standard call returning about 20 posts, and there is no developer account or approval step before the first request.</p>
<h2>Frequently Asked Questions</h2>
<h3>What fields does the X API return by default for a tweet?</h3>
<p>Three: id, text and edit_history_tweet_ids. Everything else, including created_at, author_id and public_metrics, has to be requested explicitly with the tweet.fields parameter. A lookup that omits tweet.fields returns exactly those three keys and nothing more.</p>
<h3>What is inside public_metrics on a tweet?</h3>
<p>Six counters: retweet_count, reply_count, like_count, quote_count, bookmark_count and impression_count. They are point-in-time values captured when the request was served, not live counters, so two requests seconds apart can disagree. Everything in public_metrics is readable with app-only auth.</p>
<h3>Why is the tweet id a string and not a number?</h3>
<p>Tweet and user ids are 64-bit integers that exceed the 53-bit safe integer range of JavaScript and of any JSON parser that decodes numbers as doubles. X serialises them as strings so they survive the round trip. Parse them as strings and compare them as strings; converting to a float silently corrupts the low digits.</p>
<h3>What is the difference between verified and verified_type on a user?</h3>
<p>verified is a boolean that says whether the account currently carries a checkmark of any kind. verified_type says which kind: blue for an X Premium subscriber, business for an organisation, government for a state account. Since paid verification launched, verified: true no longer implies the legacy notability check, so code that treats it as a trust signal needs verified_type as well.</p>
<h3>How do I get the author of a tweet in the same response?</h3>
<p>Ask for the expansion. author_id on the post is only an id; adding expansions=author_id makes X return the matching User object in a separate includes.users array, keyed by that id. The user is not nested inside the post, so your code has to join the two arrays on the id.</p>
<h2>Related Reading</h2>
<ul>
<li><a href="https://www.getxapi.com/blogs/x-twitter-api-error-codes">X API error codes reference</a>, what comes back when a request fails instead of returning these objects</li>
<li><a href="https://www.getxapi.com/blogs/twitter-advanced-search-operators">Twitter advanced search operators</a>, the query side that produces these objects in bulk</li>
<li><a href="https://www.getxapi.com/twitter-api-rate-limits">Twitter API rate limits</a>, how many of these responses you can pull per window</li>
<li><a href="https://www.getxapi.com/blogs/python-twitter-api-tutorial">Python Twitter API tutorial</a>, parsing these fields in practice</li>
</ul>
<hr />
<p><em>Originally published on <a href="https://www.getxapi.com/blogs/x-twitter-api-object-reference">getxapi.com</a>, where the reference is kept current as X changes the objects.</em></p>
]]></content:encoded></item></channel></rss>