apimastodon

How to use the Mastodon API to post a status update with an image


Using the Mastodon API, I'm trying to post a status update to Mastodon which includes an image. This is not working for me.

It is my understanding that, to post a status update that includes an image, I first have to post the image to Mastodon. This works for me, with a version of the code that is an answer to this question.

I then take the id of the media that has been successfully submitted, and try to post a status update, referencing that id as an included piece of media. This results in the status update being posted, but the media not being included.

The relevant part of my PHP curl statement is this:

$body = [
    'status'        => $desc,
    'media_ids'     => array($media_id)
];

curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($body));

The above posts a status update with $desc as the content, but without an inclusion of an image. The $media_id is an actual id, extracted from the json response after posting an image to https://mastodon.social/api/v1/media. The id looks like this: 1097111113111806655.

I'm guessing I'm not defining the body correctly. But, having tried a number of variations, I'm at a loss as to what it's supposed to be.

Any ideas?


Solution

  • Turns out, the trick is to post the body as JSON.

    $headers = [
        'Authorization: Bearer [TOKEN]',
        'Content-Type: application/json'
    ];
                        
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,"https://[INSTANCE]/api/v1/statuses");
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
                        
    $status_data = array(
        "status" => $desc,
        "language" => "eng",
        "visibility" => "public"
    );
    $status_data['media_ids'] = array($media_id);
                        
    $post_data = json_encode($status_data);
    
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $server_output = curl_exec($ch);
    curl_close($ch);
    

    But... it seems there's more to it: When using the image ID immediately after a successful upload, the status update, with the image ID, doesn't always show the image ID. I'm surmising there's processing time, after uploading, during which including the image in a status update results in no image actually being included.

    At first, after uploading an image, I waited a few seconds before also posting the status update. Then I upped that to 20 seconds, but even then the image wouldn't always be included in the status update. Now, I post the status update a full 30 minutes after uploading the image. This works.