Twitter API v2
twitter · Social
Twitter API v2 available endpoints
Authentication
Sample Requests
Returns recent DM Events across DM conversations
Hover any highlighted part to learn what it does
curl -X GET "https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/dm_events?expansions=attachments.media_keys%2Cparticipant_ids%2Creferenced_tweets.id%2Csender_id&event_types=MessageCreate%2CParticipantsLeave&max_results=100&user.fields=created_at%2Cdescription%2Centities%2Cid%2Clocation%2Cname%2Cpinned_tweet_id%2Cprofile_image_url%2Cprotected%2Cpublic_metrics%2Curl%2Cusername%2Cverified%2Cverified_type%2Cwithheld&media.fields=alt_text%2Cduration_ms%2Cheight%2Cmedia_key%2Cnon_public_metrics%2Corganic_metrics%2Cpreview_image_url%2Cpromoted_metrics%2Cpublic_metrics%2Ctype%2Curl%2Cvariants%2Cwidth&tweet.fields=attachments%2Cauthor_id%2Ccontext_annotations%2Cconversation_id%2Ccreated_at%2Cedit_controls%2Cedit_history_tweet_ids%2Centities%2Cgeo%2Cid%2Cin_reply_to_user_id%2Clang%2Cnon_public_metrics%2Corganic_metrics%2Cpossibly_sensitive%2Cpromoted_metrics%2Cpublic_metrics%2Creferenced_tweets%2Creply_settings%2Csource%2Ctext%2Cwithheld&dm_event.fields=attachments%2Ccreated_at%2Cdm_conversation_id%2Cevent_type%2Cid%2Cparticipant_ids%2Creferenced_tweets%2Csender_id%2Ctext&pagination_token=example"
import requests
params = {
"expansions": "attachments.media_keys,participant_ids,referenced_tweets.id,sender_id",
"event_types": "MessageCreate,ParticipantsLeave",
"max_results": "100",
"user.fields": "created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld",
"media.fields": "alt_text,duration_ms,height,media_key,non_public_metrics,organic_metrics,preview_image_url,promoted_metrics,public_metrics,type,url,variants,width",
"tweet.fields": "attachments,author_id,context_annotations,conversation_id,created_at,edit_controls,edit_history_tweet_ids,entities,geo,id,in_reply_to_user_id,lang,non_public_metrics,organic_metrics,possibly_sensitive,promoted_metrics,public_metrics,referenced_tweets,reply_settings,source,text,withheld",
"dm_event.fields": "attachments,created_at,dm_conversation_id,event_type,id,participant_ids,referenced_tweets,sender_id,text",
"pagination_token": "example"
}
response = requests.get(
"https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/dm_events",
params=params,
)
print(response.json())const url = new URL('https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/dm_events');
url.searchParams.set('expansions', 'attachments.media_keys,participant_ids,referenced_tweets.id,sender_id');
url.searchParams.set('event_types', 'MessageCreate,ParticipantsLeave');
url.searchParams.set('max_results', '100');
url.searchParams.set('user.fields', 'created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld');
url.searchParams.set('media.fields', 'alt_text,duration_ms,height,media_key,non_public_metrics,organic_metrics,preview_image_url,promoted_metrics,public_metrics,type,url,variants,width');
url.searchParams.set('tweet.fields', 'attachments,author_id,context_annotations,conversation_id,created_at,edit_controls,edit_history_tweet_ids,entities,geo,id,in_reply_to_user_id,lang,non_public_metrics,organic_metrics,possibly_sensitive,promoted_metrics,public_metrics,referenced_tweets,reply_settings,source,text,withheld');
url.searchParams.set('dm_event.fields', 'attachments,created_at,dm_conversation_id,event_type,id,participant_ids,referenced_tweets,sender_id,text');
url.searchParams.set('pagination_token', 'example');
const response = await fetch(url);
const data = await response.json();
console.log(data);package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
baseURL, _ := url.Parse("https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/dm_events")
q := baseURL.Query()
q.Set("expansions", "attachments.media_keys,participant_ids,referenced_tweets.id,sender_id")
q.Set("event_types", "MessageCreate,ParticipantsLeave")
q.Set("max_results", "100")
q.Set("user.fields", "created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld")
q.Set("media.fields", "alt_text,duration_ms,height,media_key,non_public_metrics,organic_metrics,preview_image_url,promoted_metrics,public_metrics,type,url,variants,width")
q.Set("tweet.fields", "attachments,author_id,context_annotations,conversation_id,created_at,edit_controls,edit_history_tweet_ids,entities,geo,id,in_reply_to_user_id,lang,non_public_metrics,organic_metrics,possibly_sensitive,promoted_metrics,public_metrics,referenced_tweets,reply_settings,source,text,withheld")
q.Set("dm_event.fields", "attachments,created_at,dm_conversation_id,event_type,id,participant_ids,referenced_tweets,sender_id,text")
q.Set("pagination_token", "example")
baseURL.RawQuery = q.Encode()
targetURL := baseURL.String()
req, _ := http.NewRequest("GET", targetURL, nil)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require "net/http"
require "json"
uri = URI("https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/dm_events")
uri.query = URI.encode_www_form({
"expansions" => "attachments.media_keys,participant_ids,referenced_tweets.id,sender_id",
"event_types" => "MessageCreate,ParticipantsLeave",
"max_results" => "100",
"user.fields" => "created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld",
"media.fields" => "alt_text,duration_ms,height,media_key,non_public_metrics,organic_metrics,preview_image_url,promoted_metrics,public_metrics,type,url,variants,width",
"tweet.fields" => "attachments,author_id,context_annotations,conversation_id,created_at,edit_controls,edit_history_tweet_ids,entities,geo,id,in_reply_to_user_id,lang,non_public_metrics,organic_metrics,possibly_sensitive,promoted_metrics,public_metrics,referenced_tweets,reply_settings,source,text,withheld",
"dm_event.fields" => "attachments,created_at,dm_conversation_id,event_type,id,participant_ids,referenced_tweets,sender_id,text",
"pagination_token" => "example"
})
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"
req = Net::HTTP::Get.new(uri)
res = http.request(req)
puts JSON.parse(res.body)<?php
$url = "https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/dm_events?" . http_build_query([
"expansions" => "attachments.media_keys,participant_ids,referenced_tweets.id,sender_id",
"event_types" => "MessageCreate,ParticipantsLeave",
"max_results" => "100",
"user.fields" => "created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld",
"media.fields" => "alt_text,duration_ms,height,media_key,non_public_metrics,organic_metrics,preview_image_url,promoted_metrics,public_metrics,type,url,variants,width",
"tweet.fields" => "attachments,author_id,context_annotations,conversation_id,created_at,edit_controls,edit_history_tweet_ids,entities,geo,id,in_reply_to_user_id,lang,non_public_metrics,organic_metrics,possibly_sensitive,promoted_metrics,public_metrics,referenced_tweets,reply_settings,source,text,withheld",
"dm_event.fields" => "attachments,created_at,dm_conversation_id,event_type,id,participant_ids,referenced_tweets,sender_id,text",
"pagination_token" => "example"
]);
$opts = ["http" => [
"method" => "GET",
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));Returns a variety of information about the Spaces specified by the requested IDs
Hover any highlighted part to learn what it does
curl -X GET "https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/spaces?ids=example&expansions=creator_id%2Chost_ids%2Cinvited_user_ids%2Cspeaker_ids%2Ctopic_ids&user.fields=created_at%2Cdescription%2Centities%2Cid%2Clocation%2Cname%2Cpinned_tweet_id%2Cprofile_image_url%2Cprotected%2Cpublic_metrics%2Curl%2Cusername%2Cverified%2Cverified_type%2Cwithheld&space.fields=created_at%2Ccreator_id%2Cended_at%2Chost_ids%2Cid%2Cinvited_user_ids%2Cis_ticketed%2Clang%2Cparticipant_count%2Cscheduled_start%2Cspeaker_ids%2Cstarted_at%2Cstate%2Csubscriber_count%2Ctitle%2Ctopic_ids%2Cupdated_at&topic.fields=description%2Cid%2Cname"
import requests
params = {
"ids": "example",
"expansions": "creator_id,host_ids,invited_user_ids,speaker_ids,topic_ids",
"user.fields": "created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld",
"space.fields": "created_at,creator_id,ended_at,host_ids,id,invited_user_ids,is_ticketed,lang,participant_count,scheduled_start,speaker_ids,started_at,state,subscriber_count,title,topic_ids,updated_at",
"topic.fields": "description,id,name"
}
response = requests.get(
"https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/spaces",
params=params,
)
print(response.json())const url = new URL('https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/spaces');
url.searchParams.set('ids', 'example');
url.searchParams.set('expansions', 'creator_id,host_ids,invited_user_ids,speaker_ids,topic_ids');
url.searchParams.set('user.fields', 'created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld');
url.searchParams.set('space.fields', 'created_at,creator_id,ended_at,host_ids,id,invited_user_ids,is_ticketed,lang,participant_count,scheduled_start,speaker_ids,started_at,state,subscriber_count,title,topic_ids,updated_at');
url.searchParams.set('topic.fields', 'description,id,name');
const response = await fetch(url);
const data = await response.json();
console.log(data);package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
baseURL, _ := url.Parse("https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/spaces")
q := baseURL.Query()
q.Set("ids", "example")
q.Set("expansions", "creator_id,host_ids,invited_user_ids,speaker_ids,topic_ids")
q.Set("user.fields", "created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld")
q.Set("space.fields", "created_at,creator_id,ended_at,host_ids,id,invited_user_ids,is_ticketed,lang,participant_count,scheduled_start,speaker_ids,started_at,state,subscriber_count,title,topic_ids,updated_at")
q.Set("topic.fields", "description,id,name")
baseURL.RawQuery = q.Encode()
targetURL := baseURL.String()
req, _ := http.NewRequest("GET", targetURL, nil)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require "net/http"
require "json"
uri = URI("https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/spaces")
uri.query = URI.encode_www_form({
"ids" => "example",
"expansions" => "creator_id,host_ids,invited_user_ids,speaker_ids,topic_ids",
"user.fields" => "created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld",
"space.fields" => "created_at,creator_id,ended_at,host_ids,id,invited_user_ids,is_ticketed,lang,participant_count,scheduled_start,speaker_ids,started_at,state,subscriber_count,title,topic_ids,updated_at",
"topic.fields" => "description,id,name"
})
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"
req = Net::HTTP::Get.new(uri)
res = http.request(req)
puts JSON.parse(res.body)<?php
$url = "https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/spaces?" . http_build_query([
"ids" => "example",
"expansions" => "creator_id,host_ids,invited_user_ids,speaker_ids,topic_ids",
"user.fields" => "created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld",
"space.fields" => "created_at,creator_id,ended_at,host_ids,id,invited_user_ids,is_ticketed,lang,participant_count,scheduled_start,speaker_ids,started_at,state,subscriber_count,title,topic_ids,updated_at",
"topic.fields" => "description,id,name"
]);
$opts = ["http" => [
"method" => "GET",
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));Returns a variety of information about the Tweet specified by the requested ID.
Hover any highlighted part to learn what it does
curl -X GET "https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/tweets?ids=example&expansions=attachments.media_keys%2Cattachments.poll_ids%2Cauthor_id%2Cedit_history_tweet_ids%2Centities.mentions.username%2Cgeo.place_id%2Cin_reply_to_user_id%2Creferenced_tweets.id%2Creferenced_tweets.id.author_id&poll.fields=duration_minutes%2Cend_datetime%2Cid%2Coptions%2Cvoting_status&user.fields=created_at%2Cdescription%2Centities%2Cid%2Clocation%2Cname%2Cpinned_tweet_id%2Cprofile_image_url%2Cprotected%2Cpublic_metrics%2Curl%2Cusername%2Cverified%2Cverified_type%2Cwithheld&media.fields=alt_text%2Cduration_ms%2Cheight%2Cmedia_key%2Cnon_public_metrics%2Corganic_metrics%2Cpreview_image_url%2Cpromoted_metrics%2Cpublic_metrics%2Ctype%2Curl%2Cvariants%2Cwidth&place.fields=contained_within%2Ccountry%2Ccountry_code%2Cfull_name%2Cgeo%2Cid%2Cname%2Cplace_type&tweet.fields=attachments%2Cauthor_id%2Ccontext_annotations%2Cconversation_id%2Ccreated_at%2Cedit_controls%2Cedit_history_tweet_ids%2Centities%2Cgeo%2Cid%2Cin_reply_to_user_id%2Clang%2Cnon_public_metrics%2Corganic_metrics%2Cpossibly_sensitive%2Cpromoted_metrics%2Cpublic_metrics%2Creferenced_tweets%2Creply_settings%2Csource%2Ctext%2Cwithheld"
import requests
params = {
"ids": "example",
"expansions": "attachments.media_keys,attachments.poll_ids,author_id,edit_history_tweet_ids,entities.mentions.username,geo.place_id,in_reply_to_user_id,referenced_tweets.id,referenced_tweets.id.author_id",
"poll.fields": "duration_minutes,end_datetime,id,options,voting_status",
"user.fields": "created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld",
"media.fields": "alt_text,duration_ms,height,media_key,non_public_metrics,organic_metrics,preview_image_url,promoted_metrics,public_metrics,type,url,variants,width",
"place.fields": "contained_within,country,country_code,full_name,geo,id,name,place_type",
"tweet.fields": "attachments,author_id,context_annotations,conversation_id,created_at,edit_controls,edit_history_tweet_ids,entities,geo,id,in_reply_to_user_id,lang,non_public_metrics,organic_metrics,possibly_sensitive,promoted_metrics,public_metrics,referenced_tweets,reply_settings,source,text,withheld"
}
response = requests.get(
"https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/tweets",
params=params,
)
print(response.json())const url = new URL('https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/tweets');
url.searchParams.set('ids', 'example');
url.searchParams.set('expansions', 'attachments.media_keys,attachments.poll_ids,author_id,edit_history_tweet_ids,entities.mentions.username,geo.place_id,in_reply_to_user_id,referenced_tweets.id,referenced_tweets.id.author_id');
url.searchParams.set('poll.fields', 'duration_minutes,end_datetime,id,options,voting_status');
url.searchParams.set('user.fields', 'created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld');
url.searchParams.set('media.fields', 'alt_text,duration_ms,height,media_key,non_public_metrics,organic_metrics,preview_image_url,promoted_metrics,public_metrics,type,url,variants,width');
url.searchParams.set('place.fields', 'contained_within,country,country_code,full_name,geo,id,name,place_type');
url.searchParams.set('tweet.fields', 'attachments,author_id,context_annotations,conversation_id,created_at,edit_controls,edit_history_tweet_ids,entities,geo,id,in_reply_to_user_id,lang,non_public_metrics,organic_metrics,possibly_sensitive,promoted_metrics,public_metrics,referenced_tweets,reply_settings,source,text,withheld');
const response = await fetch(url);
const data = await response.json();
console.log(data);package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
baseURL, _ := url.Parse("https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/tweets")
q := baseURL.Query()
q.Set("ids", "example")
q.Set("expansions", "attachments.media_keys,attachments.poll_ids,author_id,edit_history_tweet_ids,entities.mentions.username,geo.place_id,in_reply_to_user_id,referenced_tweets.id,referenced_tweets.id.author_id")
q.Set("poll.fields", "duration_minutes,end_datetime,id,options,voting_status")
q.Set("user.fields", "created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld")
q.Set("media.fields", "alt_text,duration_ms,height,media_key,non_public_metrics,organic_metrics,preview_image_url,promoted_metrics,public_metrics,type,url,variants,width")
q.Set("place.fields", "contained_within,country,country_code,full_name,geo,id,name,place_type")
q.Set("tweet.fields", "attachments,author_id,context_annotations,conversation_id,created_at,edit_controls,edit_history_tweet_ids,entities,geo,id,in_reply_to_user_id,lang,non_public_metrics,organic_metrics,possibly_sensitive,promoted_metrics,public_metrics,referenced_tweets,reply_settings,source,text,withheld")
baseURL.RawQuery = q.Encode()
targetURL := baseURL.String()
req, _ := http.NewRequest("GET", targetURL, nil)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require "net/http"
require "json"
uri = URI("https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/tweets")
uri.query = URI.encode_www_form({
"ids" => "example",
"expansions" => "attachments.media_keys,attachments.poll_ids,author_id,edit_history_tweet_ids,entities.mentions.username,geo.place_id,in_reply_to_user_id,referenced_tweets.id,referenced_tweets.id.author_id",
"poll.fields" => "duration_minutes,end_datetime,id,options,voting_status",
"user.fields" => "created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld",
"media.fields" => "alt_text,duration_ms,height,media_key,non_public_metrics,organic_metrics,preview_image_url,promoted_metrics,public_metrics,type,url,variants,width",
"place.fields" => "contained_within,country,country_code,full_name,geo,id,name,place_type",
"tweet.fields" => "attachments,author_id,context_annotations,conversation_id,created_at,edit_controls,edit_history_tweet_ids,entities,geo,id,in_reply_to_user_id,lang,non_public_metrics,organic_metrics,possibly_sensitive,promoted_metrics,public_metrics,referenced_tweets,reply_settings,source,text,withheld"
})
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"
req = Net::HTTP::Get.new(uri)
res = http.request(req)
puts JSON.parse(res.body)<?php
$url = "https://api.apis.guru/v2/specs/twitter.com/current/2.61/2/tweets?" . http_build_query([
"ids" => "example",
"expansions" => "attachments.media_keys,attachments.poll_ids,author_id,edit_history_tweet_ids,entities.mentions.username,geo.place_id,in_reply_to_user_id,referenced_tweets.id,referenced_tweets.id.author_id",
"poll.fields" => "duration_minutes,end_datetime,id,options,voting_status",
"user.fields" => "created_at,description,entities,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,verified_type,withheld",
"media.fields" => "alt_text,duration_ms,height,media_key,non_public_metrics,organic_metrics,preview_image_url,promoted_metrics,public_metrics,type,url,variants,width",
"place.fields" => "contained_within,country,country_code,full_name,geo,id,name,place_type",
"tweet.fields" => "attachments,author_id,context_annotations,conversation_id,created_at,edit_controls,edit_history_tweet_ids,entities,geo,id,in_reply_to_user_id,lang,non_public_metrics,organic_metrics,possibly_sensitive,promoted_metrics,public_metrics,referenced_tweets,reply_settings,source,text,withheld"
]);
$opts = ["http" => [
"method" => "GET",
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));Postman Setup Guide
- See official documentation for authentication and setup.
What can you build with Twitter API v2?
Twitter API v2 is a Social API. Developers commonly use social APIs for:
- adding social login (Sign in with Google/Twitter)
- fetching user-generated content for analysis
- scheduling and publishing social posts
- tracking mentions and engagement metrics
- building community dashboards
No authentication required. This API is open — no signup or key needed. Ideal for quick prototypes and public-facing features. Twitter API v2 is free to use, making it a low-risk choice to experiment with.
New to APIs? Read our beginner's guide · Learn about API keys · What is REST?