Workflow to post media tweets and DM attachments
Use this workflow when a PHP app needs to publish a media tweet. Use it too when the app replies with media. It also covers a direct message with an uploaded local file.POST /x/tweets accepts public media URLs through media. Send up to 4 image URLs or exactly 1 MP4 video URL. The video can be up to 100 MB. Do not mix video with other media. For replies, set replyToTweetID to the parent tweet ID. $client->x->media->upload() maps to POST /x/media. Use its $media->mediaID only for the one-item mediaIDs array on $client->x->dm->send().
Use $client->x->tweets->raw->create() to capture the durable write action. Send a unique Idempotency-Key. Store id, request.hash, billing, result, and statusUrl. Poll while terminal is false. Retry only when safeToRetry is true, using a new key.write_action_id and charged_credits. Before retrying a pending tweet or reply, poll Get Write Action Status. Store tweet_id on the CMS, queue job, or agent state after confirmed writes. Store $dm->messageID, $media->mediaID, account, user_id, and send status. Put them on the support ticket or CRM note. Keep DM body text in private systems. Shared logs, public artifacts, queue status, and agent handoffs should omit full DM bodies. They should store message_id, optional media_id, account, user_id, and send status. Leave generated replyToMessageID unset even if SDK params expose it. The REST endpoint rejects DM reply threading. Text-only tweet and reply writes cost 30 credits. Tweet media adds 2 credits per started MB across attached files. Uploading media costs 10 credits. Sending the DM costs 10 credits. Do not pass uploaded $media->mediaID values to $client->x->tweets->create(). That method uses media with public media URLs.
$client->x->dm->deleteMessage() deletes a DM.