メインコンテンツへスキップ
このガイドでは、X API v2 のメディアアップロード endpoint を使って、初回のメディアアップロードリクエストを実行する方法を説明します。 本ガイドでは、分割送信の POST /2/media/upload endpoint を用いて動画をアップロードします。これは単一画像のアップロードとは異なるワークフローが必要です。 動画や分割アップロードの場合は、次の手順を実行します。
  1. INIT コマンドでアップロードを初期化する
  2. APPEND コマンドで各バイトチャンクをアップロードする
  3. FINALIZE コマンドでアップロードを完了する
注: Python で実装された例は、サンプルコードを参照してください。

認証

このガイドのサンプルを実行するには、OAuth 2 による認証を使用する必要があります。 CONSUMER_KEYCONSUMER_SECRETACCESS_KEYACCESS_TOKEN は、developer portal のダッシュボード内の Project の App で確認できます。

ステップ 1 : POST media/upload (INIT)

INIT コマンドのリクエストは、ファイルのアップロードセッションを開始するために使用します。これにより、以降のすべてのリクエストで使用する必要がある media_id が返されます。INIT コマンドが成功した後の次のステップは APPEND コマンドです。 メディアファイルに関する制約と要件については、Best Practices を参照してください。 リクエスト例
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'
注意: 生の HTTP リクエストを送信する場合、リクエストは multipart/form-data または application/x-www-form-urlencoded の POST 形式である必要があります。
レスポンス例
{
    "data":
    {
        "id":"1880028106020515840",
        "media_key":"13_1880028106020515840",
        "expires_after_secs":1295999
    }
}
レスポンスには、メディア識別子である id(文字列)と media_key(文字列)が含まれます。expires_after_secs 秒以内にファイル全体をアップロードする必要があります。

ステップ 2 : POST media/upload (APPEND)

APPEND コマンドは、メディアファイルのチャンク(連続したバイト範囲)をアップロードするために使用します。たとえば、3 MB のファイルを 1 MB のチャンク 3 つに分割し、APPEND コマンドのリクエストを 3 回送ってアップロードできます。ファイル全体のアップロードが完了したら、次のステップとして FINALIZE コマンドを呼び出します。
メディアファイルを小さなチャンクでアップロードすることには次の利点があります:
  • 低帯域幅のネットワーク環境でも信頼性と成功率が向上
  • アップロードの一時停止と再開が可能
  • 各チャンクを個別に再試行可能
  • 変化するネットワーク状況(例: セルラー回線のクライアント)に合わせてチャンクサイズを調整可能
リクエスト例
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 はファイルチャンクの通し番号(順序インデックス)です。0〜999 の範囲(両端を含む)で指定します。最初のセグメントは 0、2 番目は 1、と順に続きます。すべてのチャンクをアップロードし終えるまで、チャンクのアップロードを続けてください。
注意: 生の HTTP リクエストを送る場合、リクエストは multipart/form-data の POST 形式である必要があります。
注意: アップロードが成功すると、HTTP 2XX が返され、レスポンスボディは空になります。

ステップ 3 : POST media/upload (FINALIZE)

APPEND コマンドでメディアファイル全体のアップロードが完了した後に、FINALIZE コマンドを呼び出す必要があります。FINALIZE コマンドのレスポンスに processing_info フィールドが含まれている場合にのみ、STATUS コマンドを使用し、成功が返されるまで待機してから Post の作成に進む必要がある場合があります。 リクエスト例
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'
注意: ローな HTTP リクエストを送信する場合、リクエストは multipart/form-dataapplication/x-www-form-urlencoded の POST 形式である必要があります。
レスポンスの例
{
    "data": {
        "id": "1880028106020515840",
        "media_key": "13_1880028106020515840",
        "size": 1024,
        "expires_after_secs": 86400,
        "processing_info": {
            "state": "pending",
            "check_after_secs": 1
        }
    }
}
レスポンスには、media_id(64ビット整数)および media_id_string(文字列)フィールドでメディア識別子が含まれます。JavaScript など長整数を正確に表現できない言語では、API レスポンスで提供される media_id_string を使用してください。 返される media_id が有効なのは expires_after_secs で示される秒数のみです。この期間を過ぎて他の API 呼び出しで media_id を使用しようとすると、Bad Request(HTTP 4xx)レスポンスになります。 レスポンスに processing_info フィールドが含まれている場合は、FINALIZE 操作のステータスをポーリングするために STATUS コマンドを使用してください。非同期の finalize 手法は、メディア処理に時間を要するケースで使用されます。将来的には、動画およびアニメーション GIF の処理は非同期 finalize のみがサポートされます。この挙動は、アップロードセッションが media_category パラメータで初期化され、かつメディアの種類が動画またはアニメーション GIF の場合に有効になります。
注意: レスポンスに processing_info フィールドが返されない場合、media_id は他の API endpoint で使用可能です。

ステップ 4 : GET media/upload (STATUS)

STATUS コマンドは、メディア処理の進行状況を定期的にポーリングして更新を取得するために使用します。STATUS コマンドの応答で succeeded が返ったら、通常は media_id を使用して Post を作成する次のステップに進めます。
注: FINALIZE コマンドの応答、または直前の STATUS コマンドの応答に processing_info フィールドが含まれている 場合に限り、STATUS コマンドを使用してください。

リクエストの例

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

レスポンス例

{
    "data":{
        "id":"1880028106020515840",
        "media_key":"13_1880028106020515840",
        "processing_info":{
            "state":"uploading" // 状態遷移フローは pending -> in_progress -> [failed|succeeded]
        }
    }
}
レスポンスボディには、メディア処理の現在の状態に関する情報を提供する processing_info フィールドが含まれています。これには state フィールドがあり、遷移は pending -> in_progress -> [failed | succeeded] の順です。state フィールドが succeeded になるまで、media_id を使用して Post やその他のエンティティを作成することはできません。

ステップ 5 : メディア付きで Tweet を投稿

認証済みユーザーに代わって、POST /2/tweets endpoint を使用し、media_id を含めて Post を作成します。 リクエスト例
curl --location 'https://api.x.com/2/tweets' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <YOUR_ACCESS_TOKEN>'
--data '{
    "text": "メディア付きのPostを投稿しました!",
     "media": {
       "media_ids": [
            "1880028106020515840"
        ]
    }
}'

サンプルレスポンス
{
    "data": {
        "edit_history_tweet_ids": [
            "1880028106020515840"
        ],
        "id": "1880028106020515840",
        "text": "メディア付きのPostを投稿しました! https://t.co/DqNyXX"
    }
}

トラブルシューティング

Media API に関する問題は、開発者フォーラムの Media API カテゴリ を参照して解決策をお探しください。
I