Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

NoTimeForCaution's avatar

Guzzle + Twitter API (Upload Image)

I'm interacting with Twitter API endpoints via GuzzleHttp. No issues with first request (INIT) which returns media_credentials for subsequent file upload.

When I attempt second request (APPEND) with actual file contents - it continuously fails with '400 Bad Request'

Here's snippet of above attempt:

// TWITTER RESPONSE FROM FIRST REQUEST => $response
// MEDIA FILE FIELD FROM FORM => $media
// IMAGE FILE CONTENTS
$baseFile = base64_encode(file_get_contents($media->path()));
// BUILD APPEND PARAMS
$paramsAppend = array('command' => 'APPEND', 'media_id' => $response->media_id, 'segment_index' => 0, 'media_data' => $baseFile);
// TWITTER API APPEND REQUEST
$postAppend = $this->client->post('media/upload.json' . '?' . http_build_query($paramsAppend));
$res = $postAppend->getStatusCode();
dd($res);

Here's the endpoint example from Twitter Docs:

// TWITTER APPEND ENDPOINT EXAMPLE
POST https://upload.twitter.com/1.1/media/upload.json?command=APPEND&media_id=123&segment_index=2&media_data=123
// MY REQUEST AS RETURNED WITH ERROR
POST https://upload.twitter.com/1.1/media/upload.json?command=APPEND&media_id=123&segment_index=2&media_data=F78

Looking through Twitter class of TwitterOauth composer package shows the same workflow behind the scenes:

$file = file_get_contents($parameters['media'])) === false
$parameters['media'] = base64_encode($file);

If I should be including raw file contents via body of request, how do I reference that in query string?

Thanks..

0 likes
1 reply
tntstudio's avatar

Here's how the request needs to look


$client->post("media/upload.json", [
            'multipart' => [
                [
                    'name'     => 'command',
                    'contents' => 'APPEND'
                ],
                [
                    'name'     => 'media_id',
                    'contents' => $media_id
                ],
                [
                    'name'     => 'segment_index',
                    'contents' => 0
                ],
                [
                    'name'     => 'media_data',
                    'contents' => base64_encode(file_get_contents($filename))
                ]
            ]
        ])->getBody();

Please or to participate in this conversation.