Skip to content
The Yoto Developer Challenge is on, with $10,000 to win!

Uploading custom cover images

You can upload custom cover images to make your MYO cards visually distinctive and personalized.

The cover image upload process works as follows:

  1. Send your image file to the Yoto API
  2. Receive back a media URL
  3. Use the URL in your playlist metadata

In this example, we’ll be uploading this custom cover image and use it in a playlist.

Custom cover art
import { readFileSync } from "node:fs";
const imageBuffer = readFileSync("./cover-image.jpg");
const imageFile = new Blob([imageBuffer]);
const url = new URL("https://api.yotoplay.com/media/coverImage/user/me/upload");
url.searchParams.set("autoconvert", "true");
url.searchParams.set("coverType", "default");
const uploadResponse = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "image/jpeg",
},
body: imageFile,
});
const uploadResult = await uploadResponse.json();

Once uploaded successfully, you’ll receive a response containing:

{
"coverImage": {
"mediaId": "uiM3MMWgQkG_zdd_EYHd93Z2OQSH5Hn069wDGdWANMc",
"mediaUrl": "https://card-content.aws.fooropa.com/1bErAD2CBDPwN88jdjBO7aVSR1OGL5DOq05fyz6PioCs~/pub/uiM3MMWgQkG_zdd_EYHd93Z2OQSH5Hn069wDGdWANMc"
}
}

You can customize the upload behavior with these query parameters:

  • autoconvert (boolean): When set to true (recommended), Yoto will automatically resize and process your image to the appropriate cover image dimensions. If set to false, your image must already be in the correct format.
  • imageUrl (string): Alternatively, you can provide a URL to an image instead of uploading a file.

We’ll be using the mediaUrl from the upload response. We’ll add this to the cover object in our playlist metadata as the imageL property.

// Using the mediaUrl from the upload response
const { mediaUrl } = uploadResult.coverImage;
const content = {
title: "My Custom Playlist",
metadata: {
cover: {
imageL: mediaUrl, // Your custom cover image
},
description: "A playlist with custom cover art",
},
content: {
chapters: [
{
key: "01",
title: "Chapter 1",
overlayLabel: "1",
tracks: [
{
key: "01",
title: "Track 1",
trackUrl: "https://example.com/audio.mp3",
type: "stream",
format: "mp3",
},
],
},
],
},
};

Your custom cover image will now be displayed as the card artwork in the Yoto app and on compatible players!

Here’s an example of a complete workflow:

export const createPlaylistWithCoverImage = async ({
imageFile,
filename = "cover-image",
title = "Playlist with Custom Cover",
streamUrl = "https://yoto.dev/music/autumn-3.mp3",
cardId,
accessToken,
}) => {
// Step 1: Upload the custom cover image
// Construct uploadURL with query parameters
const url = `https://api.yotoplay.com/media/coverImage/user/me/upload?autoconvert=true&coverType=default&filename=${filename}`;
// Upload the cover image file
const uploadResponse = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "image/jpeg",
},
body: imageFile,
});
const uploadResult = await uploadResponse.json();
// The response should contain the mediaUrl
const { mediaUrl } = uploadResult.coverImage;
console.log("Cover image uploaded successfully:", {
mediaUrl,
});
// Step 2: Create streaming playlist content using the uploaded cover image
const chapters = [
{
key: "01",
title: title,
overlayLabel: "1",
tracks: [
{
key: "01",
type: "stream",
format: "mp3",
title: title,
trackUrl: streamUrl,
display: {
icon16x16: "yoto:#aUm9i3ex3qqAMYBv-i-O-pYMKuMJGICtR3Vhf289u2Q",
},
},
],
display: {
icon16x16: "yoto:#aUm9i3ex3qqAMYBv-i-O-pYMKuMJGICtR3Vhf289u2Q",
},
},
];
const content = {
title: title,
content: { chapters },
metadata: {
cover: {
imageL: mediaUrl, // Using the uploaded cover image
},
description: `Streaming playlist with custom cover art`,
},
};
if (cardId) {
// specify a cardId to update an existing card
content.cardId = cardId;
}
// Step 3: Create the card with the custom cover image
const createResponse = await fetch("https://api.yotoplay.com/content", {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(content),
});
const card = await createResponse.json();
console.log(
"Streaming playlist created successfully with custom cover image!"
);
return card;
};