Uploading custom icons
You can use any of our public icons when creating your content, but you can also upload your own.
The icon upload process works as follows:
- Send your image file to the Yoto API
- Receive back an identifier
- Use the identifier in your playlist
In this example, we’ll be uploading the motorbike emoji icon
from the Noto Emoji set.
Upload your icon
import { readFileSync } from "node:fs";
const iconBuffer = readFileSync("./emoji-motorbike.png");
const iconFile = new Blob([iconBuffer]);
const formData = new FormData();
formData.append("file", iconFile);
const url = new URL(
"https://api.yotoplay.com/media/displayIcons/user/me/upload"
);
url.searchParams.set("autoConvert", "true");
url.searchParams.set("filename", "emoji-motorbike");
const uploadResponse = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
},
body: formData,
});
const uploadResult = await uploadResponse.json();
Upload parameters
You can customize the upload behavior with these query parameters:
-
autoConvert(boolean): When set totrue(recommended), Yoto will automatically resize and process your image to 16×16 pixels. If set tofalse, your image must already be exactly 16×16 pixels in PNG or GIF format. -
filename(string): Optional custom filename for your icon. The file extension will be automatically determined from the uploaded file’s MIME type.
Using your uploaded icon
Once uploaded successfully, you’ll receive a response containing:
{
"displayIcon": {
"mediaId": "XBkuY6DBFn5iRfFS6nV6CTWaCrEvBOOX8nzV9Y64h8I",
"userId": "auth0|userHash",
"displayIconId": "683736c62fd7c5cd177d206f",
"url": "https://media-secure.aws.com/icons/mlWc6s-JG",
"new": true
}
}
The mediaId is what you’ll use in your content. Reference it with the yoto:# prefix:
const chapters = [
{
key: "01",
title: "Chapter 1",
display: {
icon16x16: `yoto:#${mediaId}`, // Your custom icon
},
tracks: [
{
key: "01",
title: "Track 1",
display: {
icon16x16: `yoto:#${mediaId}`, // Same icon for track
},
// ... rest of track data
},
],
},
];
Your custom icon will now display on your Yoto player when this content is playing!
Here’s an example of a complete workflow:
Show complete example
import { readFileSync } from "node:fs";
export const createCustomIconCard = async ({ iconPath, filename = "my-custom-icon", title = "Custom Icon Streaming Card", cardId, accessToken,}) => { // Step 1: Upload the custom icon const iconBuffer = readFileSync(iconPath); const iconFile = new Blob([iconBuffer]);
const url = `https://api.yotoplay.com/media/displayIcons/user/me/upload?autoConvert=true&filename=${filename}`;
const uploadResponse = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${accessToken}`, "Content-Type": "image/png", }, body: iconFile, });
const uploadResult = await uploadResponse.json();
// The response should contain the mediaId const { mediaId } = uploadResult.displayIcon;
console.log("Icon uploaded successfully:", { mediaId, });
// Step 2: Create streaming card content using the uploaded icon // Here, we're making a streaming playlist for simplicity const chapters = [ { key: "01", title: title, overlayLabel: "1", tracks: [ { key: "01", type: "stream", format: "mp3", title: title, trackUrl: "https://yoto.dev/audio/autumn-3.mp3", display: { icon16x16: `yoto:#${mediaId}`, // Using the uploaded icon }, }, ], display: { icon16x16: `yoto:#${mediaId}`, // Using the uploaded icon }, }, ];
const content = { title: title, content: { chapters }, metadata: { description: `Streaming card with custom ${filename} icon`, }, };
if (cardId) { // specify a cardId to update an existing card content.cardId = cardId; }
// Step 3: Create the card with the custom icon 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 card created successfully with custom icon!");
return card;};