TwitterAPIs Docs
API ReferenceSpaces

X Spaces API | Get Twitter Space Metadata and Speakers

Look up a single X Space by its id and get back its title, lifecycle state, host, topics, timing, audience counts and its admin, speaker and listener roster. Works for a Space that is scheduled, running or already ended. Billed at $0.0008 per call. Cost: $0.0008 per call.

GET spaces/info returns everything X exposes about one Space: title, state (Scheduled, Running or Ended), content type, the host profile, topics, the wrapper tweet, scheduled and actual start and end times, peak live listener count, replay view count, and the admin, speaker and listener rosters. It takes the Space id from a x.com/i/spaces/<id> URL and costs $0.0008 per call. Note that X does not retain the listener roster after a Space ends, so listeners is empty for an ended Space while the audience counts remain.

GET
/spaces/info

Authorization

bearerAuth
AuthorizationBearer <token>

Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>.

In: header

Query Parameters

id*string

The Space id, the trailing token in a x.com/i/spaces/ URL. 5-32 alphanumeric characters.

with_listeners?boolean

Include the listener roster. Defaults to true. X does not retain this roster after a Space ends, so it comes back empty for an ended Space regardless of this flag.

with_replays?boolean

Include replay availability and related metadata. Defaults to true.

fields?string

Comma-separated list of dotted field paths to keep in the response (one parameter, never repeated), applied to every object in the returned lists and to nested objects (for example fields=id,text,author.username; the list's own name may prefix a path, fields=tweets.id). A path prefix that lands on an array applies to each element (media.media_url_https). Pagination and envelope keys (next_cursor, cursor, has_more, count, partial, error, message, reason) are always kept. Unknown paths are ignored; up to 50 paths of up to 6 segments. Projection never changes status codes or billing, and applies to data reads only: account, feedback, session status, monitor (other than deliveries), webhook and stream-compat reads return their bodies unchanged.

compact?string

Set to 1 (or true) to apply the built-in compact preset: ids, url, text, created_at, lang, the engagement counts, the is_retweet/is_reply/is_quote flags, conversation ids, the author's id/username/name/followers_count/verification, and the quoted or retweeted tweet's id/url/author username. The preset trims what it recognises and leaves alone what it would empty, so it never turns a body into {}. Combine with fields to add paths on top of the preset. Typically cuts a tweet page by 70 to 90 percent for LLM tool callers.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/spaces/info?id=1RKZzjkoYRAKB&with_listeners=true&with_replays=true&fields=id%2Ctext%2Ccreated_at%2Cauthor.username&compact=1"
{  "space": {    "id": "1RKZzjkoYRAKB",    "title": "TIME TO BUILD!",    "state": "Ended",    "content_type": "visual_audio",    "media_key": "28_2042268179733643265",    "created_at": 1775749652198,    "scheduled_start": 1775840400000,    "started_at": 1775840398722,    "ended_at": 1775842790853,    "updated_at": 1775842791870,    "total_live_listeners": 264,    "total_replay_watched": 6290,    "is_space_available_for_replay": true,    "is_space_available_for_clipping": true,    "is_locked": false,    "is_muted": false,    "is_employee_only": false,    "no_incognito": false,    "disallow_join": false,    "is_subscribed": false,    "max_admin_capacity": 3,    "max_guest_sessions": 10,    "narrow_cast_space_type": 0,    "conversation_controls": 0,    "topics": [      {        "topic_id": "848920371311001600",        "name": "Technology"      },      {        "topic_id": "857879302733418496",        "name": "Entrepreneurship"      }    ],    "creator": {      "id": "825531272621654016",      "username": "TheBestOfAdam",      "name": "Adam Soccolich"    },    "tweet": {      "id": "2042648800989233184",      "text": "https://t.co/TARX17sERY"    },    "community_id": "1471580197908586507",    "mentioned_user_ids": [      "1254214946751049729"    ],    "admins": [      {        "user_id": "825531272621654016",        "screen_name": "TheBestOfAdam",        "display_name": "Adam Soccolich",        "avatar_url": "https://pbs.twimg.com/profile_images/...",        "periscope_user_id": "1WLERGNWdqRQb",        "is_verified": true,        "is_muted_by_admin": false,        "is_muted_by_guest": false,        "community_role": "Moderator",        "start": 1775840398860      }    ],    "speakers": [],    "listeners": []  }}
{  "error": "bad_request",  "message": "Missing or malformed parameter. Fix the request before retrying."}
{  "error": "unauthorized",  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."}
{  "error": "insufficient_credits",  "message": "Your balance is exhausted. Top up your credits to continue."}
{  "error": "forbidden",  "message": "X refused this resource for the acting account: on a read, the account is not a participant in the DM thread, the target is protected or has blocked it, or the session was attestation-blocked for calling from a datacenter or rotating IP; on a write, the account is not authorized for the action or has no logged-in session. The credentials are still valid, so do not re-register."}
{  "error": "not_found",  "message": "The resource does not exist, for example a deleted tweet or a private account."}
{  "error": "rate_limited",  "message": "Too many requests. Back off and retry with exponential backoff."}
{  "error": "server_error",  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."}

Pricing

UnitPrice
Per call$0.0008
Per 1,000 calls$0.80

When to use

Use this when you have a Space id or URL and need its details: who hosted it, who spoke, what it was about, when it ran and how large the audience was. It is the read half of the Spaces surface. It does not return the audio itself.

Notes

  • An ended Space returns an EMPTY listeners array even with with_listeners=true. X does not retain the per-person listener roster once a Space finishes; total_live_listeners and total_replay_watched still reflect the real audience. admins and speakers do survive.
  • Timestamps are all millisecond-epoch numbers. X itself is inconsistent here, sending started_at as a number and ended_at as a string in the same payload; both are normalised to numbers so you can subtract them directly.
  • 404 means the id resolved to no Space, which includes a Space the host deleted. 400 means the id was not a plausible Space id.
  • This endpoint does not return the Space audio.
  • Tweet Detail: Fetch a single tweet's full object by ID.
  • User Info by Username: Fetch a full profile by @handle.
  • Trends: Read the current trending topics for a location, an Explore tab or a trend label.

FAQ

Where do I find a Space id?

It is the trailing token of the Space URL. In https://x.com/i/spaces/1RKZzjkoYRAKB the id is 1RKZzjkoYRAKB. A /peek suffix on the URL is not part of the id.

Why is the listeners array empty for a Space I know had an audience?

Because the Space has ended. X drops the per-person listener roster once a Space finishes and we pass through what X returns rather than inventing entries. The audience size is still available as total_live_listeners (peak concurrent while live) and total_replay_watched (replay views since).

Does this work for a Space that has not started yet?

Yes. A scheduled Space returns state Scheduled or NotStarted with scheduled_start set and started_at 0.

Can I get the audio recording of a Space?

Not from this endpoint, which returns metadata only.

Does it work for video Spaces?

Yes. A Space where the host enabled video comes back with content_type visual_audio; everything else about the response is the same.