Interested in an on-premise deployment or AI transformation? Calculate your AI costs. Call/text 📞 (571) 293-0242

HeyGen Integration

Overview

HeyGen provides AI-powered video generation capabilities with avatars and voices. The External Service Proxy API allows you to create videos programmatically using HeyGen's templates and avatars.

Developer


Prerequisites

  • HeyGen API credentials configured for your organization
  • See Credential Setup for configuration details
  • Valid API key or token for authentication

List Templates

Get all available video templates.

Endpoint:

POST /api/ai-proxy/orgs/{org}/services/heygen/list-templates/

Request:

{}

Response:

{
  "data": {
    "templates": [
      {
        "template_id": "abc123",
        "name": "Training Template"
      }
    ]
  }
}

Frontend Example:

async function listTemplates(org, apiKey) {
  const response = await fetch(
    `/api/ai-proxy/orgs/${org}/services/heygen/list-templates/`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Api-Key ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({})
    }
  );

  const data = await response.json();
  return data.data.templates;
}

List Avatars

Get all available avatars.

Endpoint:

POST /api/ai-proxy/orgs/{org}/services/heygen/list-avatars/

Request:

{}

Response:

{
  "data": {
    "avatars": [
      {
        "avatar_id": "Abigail_expressive_2024112501",
        "avatar_name": "Abigail (Upper Body)"
      }
    ]
  }
}

Frontend Example:

async function listAvatars(org, apiKey) {
  const response = await fetch(
    `/api/ai-proxy/orgs/${org}/services/heygen/list-avatars/`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Api-Key ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({})
    }
  );

  const data = await response.json();
  return data.data.avatars;
}

List Voices

Get all available voices.

Endpoint:

POST /api/ai-proxy/orgs/{org}/services/heygen/list-voices/

Request:

{}

Response:

{
  "data": {
    "voices": [
      {
        "voice_id": "f38a635bee7a4d1f9b0a654a31d050d2",
        "name": "Chill Brian",
        "language": "English"
      }
    ]
  }
}

Frontend Example:

async function listVoices(org, apiKey) {
  const response = await fetch(
    `/api/ai-proxy/orgs/${org}/services/heygen/list-voices/`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Api-Key ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({})
    }
  );

  const data = await response.json();
  return data.data.voices;
}

Generate Video

Avatar-based Video Generation

Generate a video using an avatar (no template required).

Endpoint:

POST /api/ai-proxy/orgs/{org}/services/heygen/generate-video/

Request:

{
  "body": {
    "test": true,
    "video_inputs": [
      {
        "character": {
          "type": "avatar",
          "avatar_id": "Abigail_expressive_2024112501",
          "avatar_style": "normal"
        },
        "voice": {
          "type": "text",
          "input_text": "Hello, this is a test video.",
          "voice_id": "f38a635bee7a4d1f9b0a654a31d050d2"
        }
      }
    ],
    "dimension": {
      "width": 1280,
      "height": 720
    }
  }
}

Request Body Parameters:

ParameterTypeRequiredDescription
testbooleanNoSet to true for test mode (no credits charged)
video_inputsarrayYesArray of video input configurations
video_inputs[].characterobjectYesAvatar configuration
video_inputs[].character.typestringYesMust be "avatar"
video_inputs[].character.avatar_idstringYesAvatar ID from List Avatars
video_inputs[].character.avatar_stylestringYesAvatar style (e.g., "normal")
video_inputs[].voiceobjectYesVoice configuration
video_inputs[].voice.typestringYesMust be "text"
video_inputs[].voice.input_textstringYesThe script text
video_inputs[].voice.voice_idstringYesVoice ID from List Voices
dimensionobjectYesVideo dimensions
dimension.widthnumberYesVideo width in pixels
dimension.heightnumberYesVideo height in pixels

Response:

{
  "data": {
    "video_id": "video_123abc"
  }
}

Frontend Example:

async function generateVideo(org, apiKey, avatarId, voiceId, script) {
  const response = await fetch(
    `/api/ai-proxy/orgs/${org}/services/heygen/generate-video/`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Api-Key ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        body: {
          test: true,
          video_inputs: [{
            character: {
              type: 'avatar',
              avatar_id: avatarId,
              avatar_style: 'normal'
            },
            voice: {
              type: 'text',
              input_text: script,
              voice_id: voiceId
            }
          }],
          dimension: { width: 1280, height: 720 }
        }
      })
    }
  );

  const result = await response.json();
  return result.data?.video_id;
}

Template-based Video Generation

Generate a video from a template.

Endpoint:

POST /api/ai-proxy/orgs/{org}/services/heygen/generate-template-video/

Path Template: /v2/template/{template_id}/generate

Required Path Parameters:

  • template_id - The ID of the template to use (get from List Templates endpoint)

Request:

{
  "path_params": {
    "template_id": "your-template-id"
  },
  "body": {
    "test": true,
    "caption": false,
    "variables": {
      "script": {
        "name": "script",
        "type": "text",
        "properties": {
          "content": "Hello, this is a test video."
        }
      }
    }
  }
}

Request Body Parameters:

ParameterTypeRequiredDescription
testbooleanNoSet to true for test mode (no credits charged)
captionbooleanNoEnable or disable captions
variablesobjectYesTemplate variables (depends on template)

Response:

{
  "data": {
    "video_id": "video_123abc"
  }
}

Frontend Example:

async function generateTemplateVideo(org, apiKey, templateId, script) {
  const response = await fetch(
    `/api/ai-proxy/orgs/${org}/services/heygen/generate-template-video/`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Api-Key ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        path_params: { template_id: templateId },
        body: {
          test: true,
          caption: false,
          variables: {
            script: {
              name: 'script',
              type: 'text',
              properties: {
                content: script
              }
            }
          }
        }
      })
    }
  );

  const result = await response.json();
  return result.data?.video_id;
}

Video Status

Check the status of a video generation job.

Endpoint:

POST /api/ai-proxy/orgs/{org}/services/heygen/video-status/

Request:

{
  "query": {
    "video_id": "video_123abc"
  }
}

Response (Processing):

{
  "data": {
    "status": "processing"
  }
}

Response (Completed):

{
  "data": {
    "status": "completed",
    "video_url": "https://..."
  }
}

Response (Failed):

{
  "data": {
    "status": "failed",
    "error": "Error message"
  }
}

Status Polling Example:

async function pollVideoStatus(org, apiKey, videoId, maxAttempts = 60, interval = 5000) {
  for (let i = 0; i < maxAttempts; i++) {
    const response = await fetch(
      `/api/ai-proxy/orgs/${org}/services/heygen/video-status/`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Api-Key ${apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          query: { video_id: videoId }
        })
      }
    );

    const result = await response.json();
    const status = result.data?.status;

    if (status === 'completed') {
      return result.data.video_url;
    } else if (status === 'failed') {
      throw new Error(result.data.error || 'Video generation failed');
    }

    // Wait before next check
    await new Promise(resolve => setTimeout(resolve, interval));
  }

  throw new Error('Video generation timed out');
}

Complete Workflow Example

This example demonstrates a complete workflow: discovering avatars and voices, generating a video, and polling for completion.

async function heygenWorkflow(org, apiKey, script) {
  try {
    // Step 1: Get available avatars
    const avatarsResponse = await fetch(
      `/api/ai-proxy/orgs/${org}/services/heygen/list-avatars/`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Api-Key ${apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({})
      }
    );
    const avatarsData = await avatarsResponse.json();
    const avatars = avatarsData.data.avatars;

    console.log('Available avatars:', avatars.map(a => a.avatar_name));

    // Step 2: Get available voices
    const voicesResponse = await fetch(
      `/api/ai-proxy/orgs/${org}/services/heygen/list-voices/`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Api-Key ${apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({})
      }
    );
    const voicesData = await voicesResponse.json();
    const voices = voicesData.data.voices;

    console.log('Available voices:', voices.map(v => v.name));

    // Step 3: Select avatar and voice
    const selectedAvatar = avatars[0];
    const selectedVoice = voices[0];

    // Step 4: Start video generation
    const generateResponse = await fetch(
      `/api/ai-proxy/orgs/${org}/services/heygen/generate-video/`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Api-Key ${apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          body: {
            test: true,
            video_inputs: [{
              character: {
                type: 'avatar',
                avatar_id: selectedAvatar.avatar_id,
                avatar_style: 'normal'
              },
              voice: {
                type: 'text',
                input_text: script,
                voice_id: selectedVoice.voice_id
              }
            }],
            dimension: { width: 1280, height: 720 }
          }
        })
      }
    );

    const generateResult = await generateResponse.json();
    const videoId = generateResult.data?.video_id;

    if (!videoId) {
      throw new Error('Failed to start video generation');
    }

    console.log('Video generation started. Video ID:', videoId);

    // Step 5: Poll for completion
    const videoUrl = await pollVideoStatus(org, apiKey, videoId);

    console.log('Video completed! URL:', videoUrl);
    return videoUrl;

  } catch (error) {
    console.error('Workflow failed:', error);
    throw error;
  }
}

// Helper function for polling
async function pollVideoStatus(org, apiKey, videoId, maxAttempts = 60, interval = 5000) {
  for (let i = 0; i < maxAttempts; i++) {
    const response = await fetch(
      `/api/ai-proxy/orgs/${org}/services/heygen/video-status/`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Api-Key ${apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          query: { video_id: videoId }
        })
      }
    );

    const result = await response.json();
    const status = result.data?.status;

    console.log(`Check ${i + 1}/${maxAttempts}: ${status}`);

    if (status === 'completed') {
      return result.data.video_url;
    } else if (status === 'failed') {
      throw new Error(result.data.error || 'Video generation failed');
    }

    await new Promise(resolve => setTimeout(resolve, interval));
  }

  throw new Error('Video generation timed out');
}

// Usage
heygenWorkflow('my-org', 'my-api-key', 'Hello! This is a demonstration of HeyGen video generation.')
  .then(videoUrl => console.log('Final video URL:', videoUrl))
  .catch(error => console.error('Failed:', error));

Copyright © ibl.ai | support@iblai.zendesk.com