X Media API
Endpoints related to retrieving and uploading Media — 11 operation(s) in the X-published contract.
Endpoints related to retrieving and uploading Media — 11 operation(s) in the X-published contract.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/x-media-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
description: X API v2 core endpoints
version: '2.168'
title: X API v2 Media API
termsOfService: https://developer.x.com/en/developer-terms/agreement-and-policy.html
contact:
name: X Developers
url: https://developer.x.com/
license:
name: X Developer Agreement and Policy
url: https://developer.x.com/en/developer-terms/agreement-and-policy.html
servers:
- description: X API
url: https://api.x.com
tags:
- name: Media
description: Endpoints related to retrieving and uploading Media
externalDocs:
description: Find out more
url: https://docs.x.com/x-api/media/introduction
paths:
/2/media:
get:
security:
- OAuth2UserToken:
- tweet.read
- UserToken: []
- BearerToken: []
tags:
- Media
summary: Get Media by media keys
operationId: getMediaByMediaKeys
parameters:
- name: media_keys
in: query
required: true
schema:
type: array
minItems: 1
maxItems: 100
items:
type: string
pattern: ^([0-9]+)_([0-9]+)$
explode: false
style: form
- $ref: '#/components/parameters/MediaFieldsParameter'
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/GetMediaByMediaKeysResponse'
default:
description: The request has failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/2/media/analytics:
get:
security:
- OAuth2UserToken:
- tweet.read
- UserToken: []
tags:
- Media
summary: Get Media analytics
operationId: getMediaAnalytics
parameters:
- name: media_keys
in: query
required: true
schema:
type: array
minItems: 1
maxItems: 100
items:
type: string
pattern: ^([0-9]+)_([0-9]+)$
explode: false
style: form
- name: start_time
in: query
required: true
schema:
type: string
format: date-time
style: form
- name: end_time
in: query
required: true
schema:
type: string
format: date-time
style: form
- name: granularity
in: query
required: false
schema:
type: string
enum:
- hourly
- daily
- total
default: daily
style: form
- $ref: '#/components/parameters/MediaAnalyticsFieldsParameter'
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/GetMediaAnalyticsResponse'
default:
description: The request has failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/2/media/metadata:
post:
security:
- OAuth2UserToken:
- media.write
- UserToken: []
tags:
- Media
summary: Create Media metadata
description: Creates metadata for a Media file.
externalDocs:
url: https://docs.x.com/x-api/media/media-metadata-create#metadata-create
operationId: createMediaMetadata
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateMediaMetadataRequest'
required: true
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/CreateMediaMetadataResponse'
default:
description: The request has failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/2/media/subtitles:
delete:
security:
- OAuth2UserToken:
- media.write
- UserToken: []
tags:
- Media
summary: Delete Media subtitles
description: Deletes subtitles for a specific Media file.
externalDocs:
url: https://docs.x.com/x-api/media/media-subtitles-delete
operationId: deleteMediaSubtitles
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteMediaSubtitlesRequest'
required: true
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteMediaSubtitlesResponse'
default:
description: The request has failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
post:
security:
- OAuth2UserToken:
- media.write
- UserToken: []
tags:
- Media
summary: Create Media subtitles
description: Creates subtitles for a specific Media file.
externalDocs:
url: https://docs.x.com/x-api/media/media-subtitles-create
operationId: createMediaSubtitles
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateMediaSubtitlesRequest'
required: true
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/CreateMediaSubtitlesResponse'
default:
description: The request has failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/2/media/upload:
get:
security:
- OAuth2UserToken:
- media.write
- UserToken: []
tags:
- Media
summary: Get Media upload status
description: Retrieves the status of a Media upload by its ID.
externalDocs:
url: https://docs.x.com/x-api/media/media-upload-status#media-upload-status
operationId: getMediaUploadStatus
parameters:
- name: media_id
in: query
required: true
schema:
$ref: '#/components/schemas/MediaId'
style: form
- name: command
in: query
required: false
schema:
type: string
enum:
- STATUS
style: form
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/GetMediaUploadStatusResponse'
default:
description: The request has failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
post:
security:
- OAuth2UserToken:
- media.write
- UserToken: []
tags:
- Media
summary: Upload a media file and get back its identifiers, including a media_key. The media field carries the file content base64-encoded in JSON bodies (raw bytes in multipart bodies); media_category is tweet_image, tweet_video, or tweet_gif for posts and ads, dm_image/dm_video/dm_gif for DMs, or subtitles. For X Ads accounts, register the returned media_key via create_media_library_item to add it to the account's media library and use it in campaigns.
description: Uploads a media file for use in posts, direct messages, or ads. The response carries the media identifiers, including the media_key used to reference the asset in later calls.
externalDocs:
url: https://docs.x.com/x-api/media/media-upload
operationId: mediaUpload
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/MediaUploadRequest'
multipart/form-data:
schema:
$ref: '#/components/schemas/MediaUploadRequest'
required: true
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/MediaUploadResponse'
default:
description: The request has failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/2/media/upload/initialize:
post:
security:
- OAuth2UserToken:
- media.write
- UserToken: []
tags:
- Media
summary: Initialize media upload
description: Initializes a media upload.
externalDocs:
url: https://docs.x.com/x-api/media/media-upload
operationId: initializeMediaUpload
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/InitializeMediaUploadRequest'
required: true
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/InitializeMediaUploadResponse'
default:
description: The request has failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/2/media/upload/{id}/append:
post:
security:
- OAuth2UserToken:
- media.write
- UserToken: []
tags:
- Media
summary: Append Media Upload
operationId: appendMediaUpload
parameters:
- name: id
in: path
required: true
schema:
type: string
pattern: ^[0-9]{1,19}$
style: simple
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/AppendMediaUploadRequest'
multipart/form-data:
schema:
$ref: '#/components/schemas/AppendMediaUploadRequest'
required: true
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/AppendMediaUploadResponse'
default:
description: The request has failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/2/media/upload/{id}/finalize:
post:
security:
- OAuth2UserToken:
- media.write
- UserToken: []
tags:
- Media
summary: Finalize Media upload
description: Finalizes a Media upload request.
externalDocs:
url: https://docs.x.com/x-api/media/media-upload
operationId: finalizeMediaUpload
parameters:
- name: id
in: path
required: true
schema:
type: string
pattern: ^[0-9]{1,19}$
style: simple
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/FinalizeMediaUploadResponse'
default:
description: The request has failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/2/media/{media_key}:
get:
security:
- OAuth2UserToken:
- tweet.read
- UserToken: []
- BearerToken: []
tags:
- Media
summary: Get Media by media key
operationId: getMediaByMediaKey
parameters:
- name: media_key
in: path
required: true
schema:
type: string
pattern: ^([0-9]+)_([0-9]+)$
style: simple
- $ref: '#/components/parameters/MediaFieldsParameter'
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/GetMediaByMediaKeyResponse'
default:
description: The request has failed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
components:
schemas:
CreateMediaMetadataMetadataPreviewImage:
type: object
required:
- media_key
properties:
media_key:
type: object
MediaUploadRequest:
type: object
required:
- media
- media_category
properties:
additional_owners:
type: string
description: Comma-separated list of user IDs who can use this media.
media:
anyOf:
- type: string
format: binary
- type: string
format: byte
description: 'The media file to upload: base64-encoded in JSON bodies, raw bytes in multipart bodies.'
media_category:
type: string
description: The category of the media being uploaded.
enum:
- tweet_image
- tweet_video
- tweet_gif
- dm_image
- dm_video
- dm_gif
- subtitles
additionalProperties: false
CreateMediaMetadataMetadataUploadSource:
type: object
required:
- upload_source
properties:
upload_source:
type: string
Media:
type: object
properties:
alt_text:
type: string
duration_ms:
type: integer
height:
type: integer
media_key:
type: string
non_public_metrics:
$ref: '#/components/schemas/MediaNonPublicMetrics'
organic_metrics:
$ref: '#/components/schemas/MediaOrganicMetrics'
preview_image_url:
type: string
promoted_metrics:
$ref: '#/components/schemas/MediaPromotedMetrics'
public_metrics:
$ref: '#/components/schemas/MediaPublicMetrics'
type:
type: string
url:
type: string
variants:
$ref: '#/components/schemas/MediaVariants'
width:
type: integer
FinalizeMediaUploadResponseDataProcessingInfo:
type: object
properties:
check_after_secs:
type: integer
description: Seconds to wait before polling status again.
progress_percent:
type: integer
description: Processing completion percentage.
state:
type: string
description: Processing state (pending, in_progress, failed, succeeded).
additionalProperties: false
MediaAnalytics:
type: object
properties:
cta_url_clicks:
type: integer
cta_watch_clicks:
type: integer
media_key:
type: string
play_from_tap:
type: integer
playback25:
type: integer
playback50:
type: integer
playback75:
type: integer
playback_complete:
type: integer
playback_start:
type: integer
timestamp:
type: string
timestamped_metrics:
$ref: '#/components/schemas/MediaAnalyticsTimestampedMetrics'
video_views:
type: integer
watch_time_ms:
type: integer
AppendMediaUploadResponseData:
type: object
properties:
expires_at:
type: integer
description: Epoch seconds when the upload session expires.
CreateMediaSubtitlesResponseData:
type: object
properties:
associated_subtitles:
type: object
description: The subtitles now associated with the media.
id:
type: string
description: The media id.
media_category:
type: string
description: The media category.
InitializeMediaUploadResponseData:
type: object
required:
- id
properties:
expires_after_secs:
type: integer
description: Seconds until the upload session expires.
id:
type: string
description: Unique identifier of the upload session.
media_key:
type: string
description: The media key for the uploaded media.
MediaId:
type: string
description: Unique identifier of a Media
pattern: ^[0-9]{1,19}$
GetMediaByMediaKeyResponse:
type: object
properties:
data:
$ref: '#/components/schemas/Media'
errors:
type: array
items:
$ref: '#/components/schemas/Problem'
FieldHydrationFailureProblem:
type: object
required:
- type
- title
- detail
- field
properties:
detail:
type: string
field:
type: string
resource_type:
type: string
section:
type: string
status:
type: integer
title:
type: string
type:
type: string
enum:
- https://api.x.com/2/problems/field-hydration-failure
MediaUploadResponseData:
type: object
required:
- id
properties:
expires_after_secs:
type: integer
description: Seconds until the upload session expires.
id:
type: string
description: Unique identifier of the media.
image:
$ref: '#/components/schemas/MediaUploadResponseDataImage'
media_key:
type: string
description: The media key for the uploaded media.
processing_info:
$ref: '#/components/schemas/MediaUploadResponseDataProcessingInfo'
size:
type: integer
description: Total size of the media in bytes.
video:
$ref: '#/components/schemas/MediaUploadResponseDataVideo'
CreateMediaSubtitlesSubtitles:
type: object
properties:
display_name:
type: string
description: Language name in a human readable form.
id:
type: string
description: The media id of the subtitle track.
pattern: ^[0-9]{1,19}$
language_code:
type: string
description: BCP47 language code of the subtitle track.
pattern: ^[A-Z]{2}$
NotAuthorizedForResourceProblem:
type: object
required:
- type
- title
- detail
- resource_type
properties:
detail:
type: string
parameter:
type: string
resource_id:
type: string
resource_type:
type: string
section:
type: string
status:
type: integer
title:
type: string
type:
type: string
enum:
- https://api.x.com/2/problems/not-authorized-for-resource
value:
type: string
MediaUploadResponseDataVideo:
type: object
properties:
video_type:
type: string
description: MIME type of the processed video.
additionalProperties: false
GetMediaUploadStatusResponse:
type: object
properties:
data:
$ref: '#/components/schemas/GetMediaUploadStatusResponseData'
errors:
type: array
items:
$ref: '#/components/schemas/Problem'
MediaVariants:
type: array
description: Each media object may have multiple display or playback variants, with different resolutions or formats.
items:
type: object
description: A single playback or display variant of a media object.
properties:
bit_rate:
type:
- integer
- 'null'
description: The bit rate of this variant, in bits per second. Absent for playlist variants.
format: int64
content_type:
type:
- string
- 'null'
description: The MIME type of this variant, for example "video/mp4" or "application/x-mpegURL".
url:
type:
- string
- 'null'
description: The URL to this media variant.
FinalizeMediaUploadResponse:
type: object
properties:
data:
$ref: '#/components/schemas/FinalizeMediaUploadResponseData'
errors:
type: array
items:
$ref: '#/components/schemas/Problem'
CreateMediaMetadataResponseData:
type: object
required:
- id
properties:
associated_metadata:
type: object
description: The metadata now associated with the media.
id:
type: string
description: The media id the metadata was attached to.
MediaNonPublicMetrics:
type: object
description: Nonpublic engagement metrics for the media at the time of the request.
properties:
playback_0_count:
type:
- integer
- 'null'
description: Number of users who started playback (0% quartile) of this video.
format: int64
playback_100_count:
type:
- integer
- 'null'
description: Number of users who completed playback (100% quartile) of this video.
format: int64
playback_25_count:
type:
- integer
- 'null'
description: Number of users who watched at least 25% of this video.
format: int64
playback_50_count:
type:
- integer
- 'null'
description: Number of users who watched at least 50% of this video.
format: int64
playback_75_count:
type:
- integer
- 'null'
description: Number of users who watched at least 75% of this video.
format: int64
GetMediaAnalyticsResponse:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/MediaAnalytics'
errors:
type: array
items:
$ref: '#/components/schemas/Problem'
CreateMediaMetadataRequest:
type: object
required:
- id
properties:
id:
type: string
description: The media id the metadata is attached to.
pattern: ^[0-9]{1,19}$
metadata:
description: User-defined metadata to associate with the media.
$ref: '#/components/schemas/CreateMediaMetadataMetadata'
CreateMediaMetadataMetadataStickerInfoStickers:
type: object
properties: {}
NotAuthorizedForFieldProblem:
type: object
required:
- type
- title
- detail
- field
properties:
detail:
type: string
field:
type: string
parameter:
type: string
resource_id:
type: string
resource_type:
type: string
section:
type: string
status:
type: integer
title:
type: string
type:
type: string
enum:
- https://api.x.com/2/problems/not-authorized-for-field
value:
type: string
FinalizeMediaUploadResponseDataImage:
type: object
properties:
h:
type: integer
description: Height in pixels.
image_type:
type: string
description: MIME type of the uploaded image.
w:
type: integer
description: Width in pixels.
additionalProperties: false
MediaUploadResponseDataProcessingInfo:
type: object
properties:
check_after_secs:
type: integer
description: Seconds to wait before polling status again.
progress_percent:
type: integer
description: Processing completion percentage.
state:
type: string
description: Processing state (pending, in_progress, failed, succeeded).
additionalProperties: false
CreateMediaMetadataMetadataStickerInfo:
type: object
required:
- stickers
properties:
stickers:
type: array
items:
$ref: '#/components/schemas/CreateMediaMetadataMetadataStickerInfoStickers'
MediaPromotedMetrics:
type: object
description: Promoted nonpublic engagement metrics for the media at the time of the request.
properties:
playback_0_count:
type:
- integer
- 'null'
description: Number of users who started playback (0% quartile) of this video.
format: int64
playback_100_count:
type:
- integer
- 'null'
description: Number of users who completed playback (100% quartile) of this video.
format: int64
playback_25_count:
type:
- integer
- 'null'
description: Number of users who watched at least 25% of this video.
format: int64
playback_50_count:
type:
- integer
- 'null'
description: Number of users who watched at least 50% of this video.
format: int64
playback_75_count:
type:
- integer
- 'null'
description: Number of users who watched at least 75% of this video.
format: int64
view_count:
type:
- integer
- 'null'
description: The number of promoted views of this video. Null when the backend returns quartile data without a view count.
format: int64
CreateMediaSubtitlesResponse:
type: object
properties:
data:
$ref: '#/components/schemas/CreateMediaSubtitlesResponseData'
errors:
type: array
items:
$ref: '#/components/schemas/Problem'
Error:
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
InvalidRequestProblem:
type: object
required:
- type
- title
- detail
properties:
detail:
type: string
parameter:
type: string
status:
type: integer
title:
type: string
type:
type: string
enum:
- https://api.x.com/2/problems/invalid-request
value:
type: string
DeleteMediaSubtitlesRequest:
type: object
required:
- id
- media_category
- language_code
properties:
id:
type: string
description: The media id of the video the subtitles belong to.
language_code:
type: string
description: The language code of the subtitles to delete.
media_category:
type: string
description: The media category of the target media.
ResourceUnavailableProblem:
type: object
required:
- type
- title
- detail
- resource_type
properties:
detail:
type: string
resource_id:
type: string
resource_type:
type: string
status:
type: integer
title:
type: string
type:
type: string
enum:
- https://api.x.com/2/problems/resource-unavailable
AppendMediaUploadResponse:
type: object
properties:
data:
$ref: '#/components/schemas/AppendMediaUploadResponseData'
errors:
type: array
items:
$ref: '#/components/schemas/Problem'
InitializeMediaUploadResponse:
type: object
properties:
data:
$ref: '#/components/schemas/InitializeMediaUploadResponseData'
errors:
type: array
items:
$ref: '#/components/schemas/Problem'
DisallowedResourceProblem:
type: object
required:
- type
- title
- detail
properties:
detail:
type: string
resource_id:
type: string
resource_type:
type: string
section:
type: string
status:
type: integer
title:
type: string
type:
type: string
enum:
- https://api.x.com/2/problems/disallowed-resource
FinalizeMediaUploadResponseData:
type: object
required:
- id
properties:
expires_after_secs:
type: integer
description: Seconds until the upload session expires.
id:
type: string
description: Unique identifier of the media.
image:
$ref: '#/components/schemas/FinalizeMediaUploadResponseDataImage'
media_key:
type: string
description: The media key for the uploaded media.
processing_info:
$ref: '#/components/schemas/FinalizeMediaUploadResponseDataProcessingInfo'
size:
type: integer
description: Total size of the media in bytes.
video:
$ref: '#/components/schemas/FinalizeMediaUploadResponseDataVideo'
CreateMediaMetadataMetadata:
type: object
properties:
allow_download_status:
$ref: '#/components/schemas/CreateMediaMetadataMetadataAllowDownloadStatus'
alt_text:
$ref: '#/components/schemas/CreateMediaMetadataMetadataAltText'
audience_policy:
type: object
content_expiration:
$ref: '#/components/schemas/CreateMediaMetadataMetadataContentExpiration'
domain_restrictions:
$ref: '#/components/schemas/CreateMediaMetadataMetadataDomainRestrictions'
found_media_origin:
$ref: '#/components/schemas/CreateMediaMetadataMetadataFoundMediaOrigin'
geo_restrictions:
type: object
management_info:
$ref: '#/components/schemas/CreateMediaMetadataMetadataManagementInfo'
preview_image:
$ref: '#/components/schemas/CreateMediaMetadataMetadataPreviewImage'
sensitive_media_warning:
type: object
shared_info:
$ref: '#/components/schemas/CreateMediaMetadataMetadataSharedInfo'
sticker_info:
$ref: '#/components/schemas/CreateMediaMetadataMetadataStickerInfo'
upload_source:
$ref: '#/components/schemas/CreateMediaMetadataMetadataUploadSource'
CreateMediaMetadataMetadataContentExpiration:
type: object
required:
- timestamp_sec
properties:
timestamp_sec:
type: number
CreateMediaMetadataMetadataFoundMediaOrigin:
type: object
required:
- provider
- id
properties:
id:
type: string
provider:
type: string
GetMediaUploadStatusResponseData:
type: object
required:
- id
# --- truncated at 32 KB (50 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/x/refs/heads/main/openapi/x-media-api-openapi.yml