Skip to main content

Overview

This guide walks through the complete process of creating and managing AI videos with SlideVid’s API, from initial setup to production deployment.

Step-by-Step Workflow

1. Authentication Setup

First, get your API key from the dashboard:
2

Store Securely

Save your API key in environment variables
# .env
SLIDEVID_API_KEY=your_api_key_here
3

Test Authentication

curl -H "x-api-key: $SLIDEVID_API_KEY" \
  https://api.slidevid.ai/v1/avatar/list

2. Choose Your Path


Workflow: From Scratch

Step 1: Fetch Available Resources

const SLIDEVID_API_KEY = process.env.SLIDEVID_API_KEY;
const BASE_URL = 'https://api.slidevid.ai/v1';

async function fetchResources() {
  // Get avatars
  const avatarsRes = await fetch(`${BASE_URL}/avatar/list`, {
    headers: { 'x-api-key': SLIDEVID_API_KEY }
  });
  const { data: { avatars } } = await avatarsRes.json();
  
  // Get voices
  const voicesRes = await fetch(`${BASE_URL}/voice/list`, {
    headers: { 'x-api-key': SLIDEVID_API_KEY }
  });
  const { data: { voices } } = await voicesRes.json();
  
  // Get music (optional)
  const musicRes = await fetch(`${BASE_URL}/music/list`, {
    headers: { 'x-api-key': SLIDEVID_API_KEY }
  });
  const { data: { music } } = await musicRes.json();
  
  return { avatars, voices, music };
}

const resources = await fetchResources();
console.log(`Found ${resources.avatars.length} avatars`);
console.log(`Found ${resources.voices.length} voices`);

Step 2: Select Resources

// Filter for English female voices
const englishFemaleVoices = resources.voices.filter(v => 
  v.language === 'English' && v.gender === 'Female'
);

// Pick a professional-looking avatar
const professionalAvatars = resources.avatars.filter(a =>
  a.situation === 'professional'
);

const selectedAvatar = professionalAvatars[0];
const selectedVoice = englishFemaleVoices[0];

console.log(`Selected: ${selectedAvatar.name} (${selectedVoice.name})`);

Step 3: Create Video

async function createVideoFromScratch() {
  const videoData = {
    type: 'class',
    title: 'Product Demo Video',
    script: `Hi! I'm excited to show you our amazing product. 
             It's designed to make your life easier and more productive.
             Let me walk you through the key features.`,
    avatarId: selectedAvatar.id,
    voiceId: selectedVoice.id,
    aspectRatio: 'ratio_16_9',
    caption: {
      enabled: true,
      preset: 'wrap1',
      alignment: 'bottom'
    },
    webhook: 'https://yoursite.com/api/webhook'
  };
  
  const response = await fetch(`${BASE_URL}/project/create`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': SLIDEVID_API_KEY
    },
    body: JSON.stringify(videoData)
  });
  
  const result = await response.json();
  
  if (result.success) {
    console.log('Video created:', result.data.projectId);
    return result.data.projectId;
  } else {
    throw new Error(result.message);
  }
}

const projectId = await createVideoFromScratch();

Step 4: Monitor Progress

Option A: Using Webhooks (Recommended)
// Set up webhook endpoint (Express.js example)
app.post('/api/webhook', async (req, res) => {
  const { event, projectId, status, video } = req.body;
  
  if (event === 'project.completed' && status === 'completed') {
    console.log('✅ Video ready:', video.url);
    
    // Save to database
    await saveVideo({
      projectId,
      url: video.url,
      thumbnail: video.thumbnail,
      duration: video.duration
    });
    
    // Notify user
    await notifyUser(projectId, video.url);
  }
  
  res.status(200).send('OK');
});
Option B: Polling (Not Recommended)
async function pollVideoStatus(projectId) {
  const maxAttempts = 60; // 5 minutes (60 * 5 seconds)
  
  for (let i = 0; i < maxAttempts; i++) {
    const response = await fetch(`${BASE_URL}/video/list`, {
      headers: { 'x-api-key': SLIDEVID_API_KEY }
    });
    
    const { data: { videos } } = await response.json();
    const video = videos.find(v => v.id === projectId);
    
    if (video.status === 'completed') {
      console.log('✅ Video ready!');
      return video;
    } else if (video.status === 'failed') {
      throw new Error('Video generation failed');
    }
    
    console.log(`Status: ${video.status} (${video.progress}%)`);
    await new Promise(r => setTimeout(r, 5000)); // Wait 5 seconds
  }
  
  throw new Error('Timeout waiting for video');
}

Workflow: With Templates

Step 1: List Templates

async function listTemplates() {
  const response = await fetch(`${BASE_URL}/template/list`, {
    headers: { 'x-api-key': SLIDEVID_API_KEY }
  });
  
  const { data: { templates } } = await response.json();
  
  console.log('Available templates:');
  templates.forEach(t => {
    console.log(`- ${t.name} (${t.type}) - ${t.variables.length} variables`);
  });
  
  return templates;
}

const templates = await listTemplates();

Step 2: Get Template Details

async function getTemplateDetails(templateId) {
  const response = await fetch(`${BASE_URL}/template/${templateId}`, {
    headers: { 'x-api-key': SLIDEVID_API_KEY }
  });
  
  const { data: { template } } = await response.json();
  
  console.log(`Template: ${template.name}`);
  console.log('Scenes:', template.scenes.length);
  console.log('Variables required:', template.variables);
  
  return template;
}

const selectedTemplate = templates[0];
const templateDetails = await getTemplateDetails(selectedTemplate.id);

Step 3: Prepare Variables

// Extract variables from template
const requiredVariables = templateDetails.variables;

// Prepare personalized data
const personalizationData = {
  name: 'Sarah Johnson',
  company: 'TechCorp Inc.',
  product: 'AI Assistant Pro',
  benefit: 'save 10 hours per week'
};

// Validate all variables are provided
const missingVars = requiredVariables.filter(v => !personalizationData[v]);
if (missingVars.length > 0) {
  throw new Error(`Missing variables: ${missingVars.join(', ')}`);
}

Step 4: Generate from Template

async function generateFromTemplate(templateId, data) {
  const videoData = {
    type: 'class',
    templateId: templateId,
    title: `Personalized video for ${data.name}`,
    aspectRatio: 'ratio_16_9',
    caption: {
      enabled: true,
      preset: 'wrap1',
      alignment: 'bottom'
    },
    scenes: templateDetails.scenes.map(scene => ({
      script: scene.script,
      variables: Object.entries(data).map(([key, value]) => ({
        key,
        value
      }))
    })),
    webhook: 'https://yoursite.com/api/webhook'
  };
  
  const response = await fetch(`${BASE_URL}/project/create`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': SLIDEVID_API_KEY
    },
    body: JSON.stringify(videoData)
  });
  
  const result = await response.json();
  return result.data.projectId;
}

const projectId = await generateFromTemplate(selectedTemplate.id, personalizationData);

Step 5: Bulk Generation

async function bulkGenerate(templateId, recipients) {
  const projectIds = [];
  
  for (const recipient of recipients) {
    try {
      const projectId = await generateFromTemplate(templateId, recipient);
      projectIds.push({ recipient: recipient.name, projectId });
      
      console.log(`✅ Created video for ${recipient.name}`);
      
      // Rate limiting: wait between requests
      await new Promise(r => setTimeout(r, 1000));
      
    } catch (error) {
      console.error(`❌ Failed for ${recipient.name}:`, error.message);
    }
  }
  
  return projectIds;
}

// Generate personalized videos for multiple recipients
const recipients = [
  { name: 'Sarah Johnson', company: 'TechCorp', product: 'AI Assistant' },
  { name: 'Mike Chen', company: 'StartupXYZ', product: 'Analytics Tool' },
  { name: 'Emma Davis', company: 'BigCorp', product: 'Cloud Platform' },
];

const projects = await bulkGenerate(selectedTemplate.id, recipients);
console.log(`Generated ${projects.length} videos`);

Complete Example: Production-Ready

Here’s a complete, production-ready implementation:
class SlideVidVideoAPI {
  constructor(apiKey, baseUrl = 'https://api.slidevid.ai/v1') {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
  }
  
  async request(endpoint, options = {}) {
    const response = await fetch(`${this.baseUrl}${endpoint}`, {
      ...options,
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': this.apiKey,
        ...options.headers
      }
    });
    
    const data = await response.json();
    
    if (!response.ok) {
      throw new Error(`API Error: ${data.message}`);
    }
    
    return data;
  }
  
  // Resources
  async getAvatars(type = 'all') {
    const { data } = await this.request(`/avatar/list?type=${type}`);
    return data.avatars;
  }
  
  async getVoices(filters = {}) {
    const params = new URLSearchParams(filters);
    const { data } = await this.request(`/voice/list?${params}`);
    return data.voices;
  }
  
  async getMusic(category = null) {
    const params = category ? `?category=${category}` : '';
    const { data } = await this.request(`/music/list${params}`);
    return data.music;
  }
  
  // Templates
  async listTemplates(type = null) {
    const params = type ? `?type=${type}` : '';
    const { data } = await this.request(`/template/list${params}`);
    return data.templates;
  }
  
  async getTemplate(templateId) {
    const { data } = await this.request(`/template/${templateId}`);
    return data.template;
  }
  
  // Video Creation
  async createVideo(videoData) {
    const { data } = await this.request('/project/create', {
      method: 'POST',
      body: JSON.stringify(videoData)
    });
    return data.projectId;
  }
  
  async listVideos(filters = {}) {
    const params = new URLSearchParams(filters);
    const { data } = await this.request(`/video/list?${params}`);
    return data.videos;
  }
  
  // High-level methods
  async createFromScratch(script, options = {}) {
    const videoData = {
      type: options.type || 'class',
      title: options.title || 'My Video',
      script,
      avatarId: options.avatarId,
      voiceId: options.voiceId,
      aspectRatio: options.aspectRatio || 'ratio_9_16',
      caption: options.caption || { enabled: true },
      webhook: options.webhook
    };
    
    return await this.createVideo(videoData);
  }
  
  async generateFromTemplate(templateId, variables, options = {}) {
    const template = await this.getTemplate(templateId);
    
    const videoData = {
      type: template.type,
      templateId,
      title: options.title || `Video from ${template.name}`,
      aspectRatio: options.aspectRatio || template.videoSettings?.aspectRatio,
      caption: options.caption,
      scenes: template.scenes.map(scene => ({
        script: scene.script,
        variables: Object.entries(variables).map(([key, value]) => ({
          key,
          value: String(value)
        }))
      })),
      webhook: options.webhook
    };
    
    return await this.createVideo(videoData);
  }
}

// Usage
const api = new SlideVidVideoAPI(process.env.SLIDEVID_API_KEY);

// Create from scratch
const projectId1 = await api.createFromScratch(
  'Welcome to our platform! Let me show you around.',
  {
    avatarId: 'avatar_123',
    voiceId: 'voice_456',
    aspectRatio: 'ratio_16_9',
    webhook: 'https://mysite.com/webhook'
  }
);

// Generate from template
const projectId2 = await api.generateFromTemplate(
  'template_789',
  {
    name: 'John Doe',
    company: 'Acme Corp'
  },
  {
    webhook: 'https://mysite.com/webhook'
  }
);

console.log('Videos created:', projectId1, projectId2);

Best Practices Summary

Use Webhooks

Always use webhooks instead of polling for better efficiency

Error Handling

Implement comprehensive error handling and retries

Rate Limiting

Respect rate limits and implement backoff strategies

Caching

Cache resources (avatars, voices) to reduce API calls

Next Steps