Recipes
Post a TikTok Carousel
Upload images via API, wait for completed status, create a TikTok carousel, and schedule it.
Post a TikTok photo carousel using API-only media upload. This flow is: upload files, finalise processing, create a TikTok carousel content item, then schedule a publish run.
Step 1: Upload images and wait for completed status
JavaScript
const apiKey = "wahlu_live_your_api_key_here";
const headers = {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
};
async function waitForMediaCompleted(brandId, mediaId, timeoutMs = 120000) {
const started = Date.now();
while (Date.now() - started < timeoutMs) {
const mediaRes = await fetch(
`https://api.wahlu.com/v1/brands/${brandId}/media/${mediaId}`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
const { data: media } = await mediaRes.json();
if (media.status === "completed") return media.id;
if (media.status === "failed") throw new Error(`Media failed: ${mediaId}`);
await new Promise((r) => setTimeout(r, 3000));
}
throw new Error(`Timed out waiting for media ${mediaId}`);
}
async function uploadAndFinaliseImage(brandId, filename, fileBuffer) {
const uploadRes = await fetch(
`https://api.wahlu.com/v1/brands/${brandId}/media/upload-url`,
{
method: "POST",
headers,
body: JSON.stringify({
filename,
content_type: "image/jpeg",
size: fileBuffer.length,
source: "upload",
}),
}
);
const { data: upload } = await uploadRes.json();
await fetch(upload.upload_url, {
method: "PUT",
headers: { "Content-Type": "image/jpeg" },
body: fileBuffer,
});
await fetch(
`https://api.wahlu.com/v1/brands/${brandId}/media/${upload.id}`,
{
method: "PATCH",
headers,
body: JSON.stringify({ status: "ready_for_processing" }),
}
);
return waitForMediaCompleted(brandId, upload.id);
}
const slidePaths = ["slide1.jpg", "slide2.jpg", "slide3.jpg", "slide4.jpg"];
const mediaIds = [];
for (const slidePath of slidePaths) {
const fileBuffer = fs.readFileSync(slidePath);
const mediaId = await uploadAndFinaliseImage(brandId, slidePath, fileBuffer);
mediaIds.push(mediaId);
}Step 2: Create a TikTok carousel post
JavaScript
const contentItemRes = await fetch(
`https://api.wahlu.com/v1/brands/${brandId}/content-items`,
{
method: "POST",
headers,
body: JSON.stringify({
name: "Coding Education Carousel",
tiktok_settings: {
description: "4 practical coding lessons for beginners. #coding #learncode",
media_ids: mediaIds,
post_type: "CAROUSEL",
privacy_level: "PUBLIC_TO_EVERYONE",
allow_comment: true,
allow_duet: true,
allow_stitch: true,
auto_add_music: false,
is_commercial_content: false,
is_aigc: false,
},
}),
}
);
const { data: contentItem } = await contentItemRes.json();
console.log(`TikTok carousel content item created: ${contentItem.id}`);Step 3: Schedule for TikTok integration
JavaScript
const integrationsRes = await fetch(
`https://api.wahlu.com/v1/brands/${brandId}/integrations`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
const { data: integrations } = await integrationsRes.json();
const tiktok = integrations.find((i) => i.platform === "tiktok");
if (!tiktok) throw new Error("No TikTok integration found for this brand");
const scheduleAt = new Date(Date.now() + 60 * 1000).toISOString(); // 1 min from now
const scheduleRes = await fetch(
`https://api.wahlu.com/v1/brands/${brandId}/publish-runs`,
{
method: "POST",
headers,
body: JSON.stringify({
content_item_id: contentItem.id,
scheduled_at: scheduleAt,
integration_ids: [tiktok.id],
approval_status: "approved",
}),
}
);
const { data: publishRun } = await scheduleRes.json();
console.log(`Scheduled: ${publishRun.id} at ${publishRun.scheduled_at}`);Step 4: Check publication result
JavaScript
const pubsRes = await fetch(
`https://api.wahlu.com/v1/brands/${brandId}/publications?limit=20`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
const { data: publications } = await pubsRes.json();
const publication = publications.find((p) => p.post_id === contentItem.id && p.platform === "tiktok");
console.log(publication?.status); // processing | published | failed
console.log(publication?.failure_reason); // null when successful