WordPress media_handle_sideload for a Sume music mp3 attachment

Download the Sume artifact URL with download_url(), then media_handle_sideload() it into the Media Library. It returns an attachment id or a WP_Error.

4 min readSume
All posts

To put a finished Sume track into the WordPress Media Library, fetch the artifact URL with download_url(), build a $file_array, and pass it to media_handle_sideload(). WordPress documents that it returns the attachment id, or a WP_Error on failure. It only works after you load three admin include files, which a REST route does not load for you.

What the function needs

The WordPress reference describes the call as media_handle_sideload( $file_array, $post_id, $desc, $post_data ).

media_handle_sideload facts (WordPress Developer Resources, read 2026-10-05)
ItemDocumented behavior
Download stepUse download_url() to fetch the remote file to a temp path
Arguments$file_array, $post_id, $desc, $post_data
ReturnAttachment id, or WP_Error
Includeswp-admin/includes/media.php, file.php and image.php must be loaded

From a Sume job to an attachment

The Music Router returns the audio in result.artifacts[] with type audio, on media.sume.com. Pull the URL from the job result in your webhook handler or a cron task. In a REST handler, the three includes are not there yet, so require them first.

require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/image.php';

function sume_sideload_track( string $url, int $post_id, string $title ) {
    $tmp = download_url( $url, 60 );
    if ( is_wp_error( $tmp ) ) {
        return $tmp;
    }
    $file = array(
        'name'     => sanitize_file_name( $title ) . '.mp3',
        'tmp_name' => $tmp,
    );
    $id = media_handle_sideload( $file, $post_id, $title );
    if ( is_wp_error( $id ) ) {
        @unlink( $tmp );
    }
    return $id;
}

Check the extension and the type

The filename you give is the one WordPress uses to decide whether the upload is allowed. Sume's docs say the router audio is usually audio/mpeg, so .mp3 is the usual name; check the artifact content_type before you hard-code it, and fall back to the extension that matches. If WordPress returns a WP_Error about the file type, log the code and the content type, and do not retry blindly.

Idempotency on your side

Sume deduplicates the generation with the Idempotency-Key header, but it cannot know that your sideload ran. If a webhook is delivered twice, store the job id as post meta and skip when it already exists. A music generation costs a fixed $0.125, while a duplicate attachment only costs disk space, so the meta check matters most for tidiness.

Before you ship

  • Run the sideload from a webhook handler or WP-Cron, not inside a page request.
  • Store the Sume job id as post meta and skip duplicates.
  • Log the WP_Error code and the artifact content type when a sideload fails.
  • Delete the temp file when WordPress returns an error.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume