Saltar al contenido principal
Esta guía te ayudará a hacer tus primeras solicitudes para subir contenido multimedia usando los endpoints de carga de medios de X API v2. En esta guía, se usan los endpoints segmentados POST /2/media/upload para subir un video, lo que requiere un flujo de trabajo distinto al de subir imágenes individuales. Para videos o cargas segmentadas, debes:
  1. Inicializar la carga con el comando INIT
  2. Subir cada segmento de bytes con el comando APPEND
  3. Completar la carga con el comando FINALIZE
Nota: Consulta este código de muestra para un ejemplo escrito en Python.

Autenticación

Para ejecutar los ejemplos de esta guía, deberás usar la autenticación OAuth 2. Puedes encontrar tus CONSUMER_KEY, CONSUMER_SECRET, ACCESS_KEY y ACCESS_TOKEN en la App de tu Proyecto en el panel del Portal de desarrolladores.

Paso 1: POST media/upload (INIT)

La solicitud del comando INIT se utiliza para iniciar una sesión de carga de archivos. Devuelve un media_id que debe usarse para realizar todas las solicitudes posteriores. El siguiente paso después de una respuesta correcta del comando INIT es el comando APPEND. Consulta las mejores prácticas para conocer las restricciones y los requisitos de los archivos multimedia. Ejemplo de solicitud
curl --location 'https://api.x.com/2/media/upload' \
    --header 'Authorization: Bearer <YOUR_ACCESS_TOKEN>' \
    --header 'Content-Type: multipart/form-data' \
    --form 'command=INIT' \
    --form 'media_type=video/mp4' \
    --form 'total_bytes=1024' \
    --form 'media_category=amplify_video'
Nota: Al realizar solicitudes HTTP sin procesar, la solicitud debe ser un POST en formato multipart/form-data o application/x-www-form-urlencoded.
Ejemplo de respuesta
{
    "data":
    {
        "id":"1880028106020515840",
        "media_key":"13_1880028106020515840",
        "expires_after_secs":1295999
    }
}
La respuesta proporciona los identificadores de medios id (string) y media_key (string). Debes cargar el archivo completo antes de que transcurran expires_after_secs segundos.

Paso 2: POST media/upload (APPEND)

El comando APPEND se utiliza para subir un fragmento (rango consecutivo de bytes) del archivo multimedia. Por ejemplo, un archivo de 3 MB podría dividirse en 3 fragmentos de 1 MB y subirse mediante 3 solicitudes del comando APPEND. Una vez que se haya subido el archivo completo, el siguiente paso es llamar al comando FINALIZE.
Subir un archivo multimedia en fragmentos pequeños tiene varias ventajas:
  • Mayor fiabilidad y tasas de éxito en condiciones de red con poco ancho de banda
  • Las cargas pueden pausarse y reanudarse
  • Se pueden reintentar individualmente los fragmentos del archivo
  • Posibilidad de ajustar el tamaño de los fragmentos para adaptarse a las condiciones cambiantes de la red; por ejemplo, en clientes móviles
Ejemplo de solicitud
curl --location 'https://api.x.com/2/media/upload' \
    --header 'Authorization: Bearer <YOUR_ACCESS_TOKEN>' \
    --header 'Content-Type: multipart/form-data' \
    --form 'command=APPEND' \
    --form 'media_id=1880028106020515840' \
    --form 'segment_index=0' \
    --form 'media=@/path/to/your/media/file.mp4'
segment_index es un índice ordenado del fragmento de archivo. Debe estar entre 0 y 999, inclusive. El primer segmento tiene índice 0, el segundo segmento tiene índice 1 y así sucesivamente. Continúa cargando los fragmentos del archivo hasta que se hayan cargado todos.
Nota: Al realizar solicitudes HTTP sin procesar, la solicitud debe ser un POST con formato multipart/form-data.
Nota: En una carga exitosa, se devolverá un HTTP 2XX con un cuerpo de respuesta vacío.

Paso 3: POST media/upload (FINALIZE)

Se debe llamar al comando FINALIZE después de cargar todo el archivo multimedia mediante comandos APPEND. Si, y solo si, la respuesta del comando FINALIZE contiene un campo processing_info, también puede ser necesario usar un comando STATUS y esperar a que indique que se ha completado correctamente antes de continuar con la creación del Post. Ejemplo de solicitud
curl --location --request POST 'https://api.x.com/2/media/upload' \
    --header 'Authorization: Bearer <YOUR_ACCESS_TOKEN>' \
    --header 'Content-Type: multipart/form-data' \
    --form 'command=FINALIZE' \
    --form 'media_id=1880028106020515840'
Nota: Al realizar solicitudes HTTP sin procesar, la solicitud debe usar los formatos POST multipart/form-data o application/x-www-form-urlencoded.
Ejemplo de respuesta
{
    "data": {
        "id": "1880028106020515840",
        "media_key": "13_1880028106020515840",
        "size": 1024,
        "expires_after_secs": 86400,
        "processing_info": {
            "state": "pending",
            "check_after_secs": 1
        }
    }
}
La respuesta proporciona un identificador de medio en los campos media_id (entero de 64 bits) y media_id_string (cadena). Usa media_id_string de la respuesta de la API en JavaScript y otros lenguajes que no pueden representar con precisión un entero largo. El media_id devuelto solo es válido durante expires_after_secs segundos. Cualquier intento de usar mediaId después de este período en otras llamadas a la API resultará en una respuesta de tipo Bad Request (HTTP 4xx). Si la respuesta contiene el campo processing_info, usa el comando STATUS para consultar el estado de la operación FINALIZE. El enfoque de finalización asíncrona se utiliza cuando el procesamiento de medios requiere más tiempo. En el futuro, todo el procesamiento de video y GIF animados solo será compatible mediante la finalización asíncrona. Este comportamiento se habilita si la sesión de carga se inicializó con el parámetro media_category, y cuando el tipo de medio es video o GIF animado.
Nota: Si en la respuesta no se devuelve el campo processing_info, entonces media_id está listo para usarse en otros endpoints de la API.

Paso 4: GET media/upload (STATUS)

El comando STATUS se utiliza para consultar periódicamente el estado de la operación de procesamiento de medios. Cuando la respuesta del comando STATUS sea succeeded, puedes pasar al siguiente paso, que normalmente es crear un Post con media_id.
Nota: El comando STATUS debe usarse solo si la respuesta del comando FINALIZE o de un comando STATUS previo contenía un campo processing_info.

Ejemplo de solicitud

curl --location --request GET 'https://api.x.com/2/media/upload?command=STATUS&media_id=1880028106020515840' \
    --header 'Authorization: Bearer <YOUR_ACCESS_TOKEN>'

Respuesta de ejemplo

{
    "data":{
        "id":"1880028106020515840",
        "media_key":"13_1880028106020515840",
        "processing_info":{
            "state":"uploading" // el flujo de transición de estado es pending -> in_progress -> [failed|succeeded]
        }
    }
}
El cuerpo de la respuesta contiene el campo processing_info, que proporciona información sobre el estado actual de la operación de procesamiento de medios. Incluye un campo state con el siguiente flujo de transición: pending -> in_progress -> [failed | succeeded]. No puede usar el media_id para crear un Post u otras entidades hasta que el campo state tenga el valor succeeded.

Paso 5 : Publicar un Tweet con contenido multimedia

Crea un Post usando el endpoint POST /2/tweets, incluyendo el media_id en nombre de un usuario autenticado. Ejemplo de solicitud
curl --location 'https://api.x.com/2/tweets' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <YOUR_ACCESS_TOKEN>'
--data '{
    "text": "¡Hice un post con contenido multimedia!",
     "media": {
       "media_ids": [
            "1880028106020515840"
        ]
    }
}'

Ejemplo de respuesta
{
    "data": {
        "edit_history_tweet_ids": [
            "1880028106020515840"
        ],
        "id": "1880028106020515840",
        "text": "¡Hice un post con contenido multimedia! https://t.co/DqNyXX"
    }
}

Solución de problemas

Si tienes problemas con las Media APIs, consulta la categoría Media API en los foros de desarrolladores para encontrar una respuesta.