Skill: michaelwang11394/video-agent (version 2.23.0)

--- name: heygen description: | [DEPRECATED — uses outdated v1/v2 endpoints] Use `create-video` for prompt-based video generation (v3 Video Agent) or `avatar-video` for precise avatar/scene control (v3 API). This legacy skill combines both workflows with deprecated endpoints. homepage: https://docs.heygen.com/reference/generate-video-agent allowed-tools: mcp__heygen__* metadata: openclaw: requires: env: - HEYGEN_API_KEY primaryEnv: HEYGEN_API_KEY --- # HeyGen API (Deprecated) > **This skill is deprecated.** Use the focused skills instead: > - **`create-video`** — Generate videos from a text prompt (Video Agent API, `POST /v3/video-agents`) > - **`avatar-video`** — Build videos with specific avatars, voices, scripts, and scenes (v3 API, `POST /v3/videos`) > > **Warning:** The endpoints documented below are v1/v2 and deprecated. The replacement skills above use the current v3 API. This skill remains for backward compatibility but will be removed in a future release. --- AI avatar video creation API for generating talking-head videos, explainers, and presentations. ## Tool Selection If HeyGen MCP tools are available (`mcp__heygen__*`), **prefer them** over direct HTTP API calls — they handle authentication and request formatting automatically. | Task | MCP Tool | Deprecated Endpoint | v3 Replacement | |------|----------|---------------------|----------------| | Generate video from prompt | [REDACTED_SECRET] | `POST /v1/video_agent/generate` | `POST /v3/video-agents` | | Check video status / get URL | `mcp__heygen__get_video` | `GET /v2/videos/{video_id}` | `GET /v3/videos/{video_id}` | | List account videos | `mcp__heygen__list_videos` | `GET /v2/videos` | `GET /v3/videos` | | Delete a video | `mcp__heygen__delete_video` | `DELETE /v2/videos/{video_id}` | `DELETE /v3/videos/{video_id}` | If no HeyGen MCP tools are available, use direct HTTP API calls with `X-[REDACTED_SECRET]` header as documented in the reference files. ## Default Workflow **Prefer Video Agent** for most video requests. Always use [prompt-optimizer.md](references/prompt-optimizer.md) guidelines to structure prompts with scenes, timing, and visual styles. **With MCP tools:** 1. Write an optimized prompt using [prompt-optimizer.md](references/prompt-optimizer.md) → [visual-styles.md](references/visual-styles.md) 2. Call [REDACTED_SECRET] with prompt and config (duration_sec, orientation, avatar_id) 3. Call `mcp__heygen__get_video` with the returned video_id to poll status and get the download URL **Without MCP tools (direct API) — use v3 endpoints from `create-video` or `avatar-video` skills:** 1. Write an optimized prompt using [prompt-optimizer.md](references/prompt-optimizer.md) → [visual-styles.md](references/visual-styles.md) 2. `POST /v3/video-agents` (replaces `/v1/video_agent/generate`) — see `create-video` skill 3. `GET /v3/videos/<id>` (replaces `/v2/videos/<id>`) — see `create-video` skill Only use the direct video API (now `POST /v3/videos`, formerly `v2/video/generate`) when user explicitly needs: - Exact script without AI modification - Specific voice_id selection - Different avatars/backgrounds per scene - Precise per-scene timing control - Programmatic/batch generation with exact specs ## Quick Reference | Task | MCP Tool | Read | |------|----------|------| | Generate video from prompt (easy) | [REDACTED_SECRET] | [prompt-optimizer.md](references/prompt-optimizer.md) → [visual-styles.md](references/visual-styles.md) → [video-agent.md](references/video-agent.md) | | Generate video with precise control | — | [video-generation.md](references/video-generation.md), [avatars.md](references/avatars.md), [voices.md](references/voices.md) | | Check video status / get download URL | `mcp__heygen__get_video` | [video-status.md](references/video-status.md) | | Add captions or text overlays | — | [captions.md](references/captions.md), [text-overlays.md](references/text-overlays.md) | | Transparent video for compositing | — | [video-generation.md](references/video-generation.md) (WebM section) | | Use with Remotion | — | [remotion-integration.md](references/remotion-integration.md) | ## Reference Files ### Foundation - [references/authentication.md](references/authentication.md) - API key setup and X-Api-Key header - [references/quota.md](references/quota.md) - Credit system and usage limits - [references/video-status.md](references/video-status.md) - Polling patterns and download URLs - [references/assets.md](references/assets.md) - Uploading images, videos, audio ### Core Video Creation - [references/avatars.md](references/avatars.md) - Listing avatars, styles, avatar_id selection - [references/voices.md](references/voices.md) - Listing voices, locales, speed/pitch - [references/scripts.md](references/scripts.md) - Writing scripts, pauses, pacing - [references/video-generation.md](references/video-generation.md) - Video generation and multi-scene videos (uses deprecated v2 endpoint — see `avatar-video` skill for v3) - [references/video-agent.md](references/video-agent.md) - One-shot prompt video generation - [references/prompt-optimizer.md](references/prompt-optimizer.md) - Writing effective Video Agent prompts (core workflow + rules) - [references/visual-styles.md](references/visual-styles.md) - 20 named visual styles with full specs - [references/prompt-examples.md](references/prompt-examples.md) - Full production prompt example + ready-to-use templates - [references/dimensions.md](references/dimensions.md) - Resolution and aspect ratios ### Video Customization - [references/backgrounds.md](references/backgrounds.md) - Solid colors, images, video backgrounds - [references/text-overlays.md](references/text-overlays.md) - Adding text with fonts and positioning - [references/captions.md](references/captions.md) - Auto-generated captions and subtitles ### Advanced Features - [references/templates.md](references/templates.md) - Template listing and variable replacement - [references/photo-avatars.md](references/photo-avatars.md) - Creating avatars from photos - [references/webhooks.md](references/webhooks.md) - Webhook endpoints and events ### Integration - [references/remotion-integration.md](references/remotion-integration.md) - Using HeyGen in Remotion compositions

path: references/authentication.md
content: ---
name: authentication
description: API key setup, X-Api-Key header, and authentication patterns for HeyGen
---

# HeyGen Authentication

All HeyGen API requests require authentication using an API key passed in the `X-Api-Key` header.

## Getting Your API Key

1. Go to https://app.heygen.com/settings?from=&nav=API
2. Log in if prompted
3. Copy your API key

## Environment Setup

Store your API key securely as an environment variable:

```bash
export HEYGEN_API_KEY="your-api-key-here"
```

For `.env` files:

```
HEYGEN_API_KEY=your-api-key-here
```

## Making Authenticated Requests

### curl

```bash
curl -X GET "https://api.heygen.com/v2/avatars" \
  -H "X-[REDACTED_SECRET]"
```

### TypeScript/JavaScript (fetch)

```typescript
const response = await fetch("https://api.heygen.com/v2/avatars", {
  headers: {
    "X-Api-Key": process.env.HEYGEN_API_KEY!,
  },
});
const { data } = await response.json();
```

### TypeScript/JavaScript (axios)

```typescript
import axios from "axios";

const client = axios.create({
  baseURL: "https://api.heygen.com",
  headers: {
    "X-Api-Key": process.env.HEYGEN_API_KEY,
  },
});

const { data } = await client.get("/v2/avatars");
```

### Python (requests)

```python
import os
import requests

response = requests.get(
    "https://api.heygen.com/v2/avatars",
    headers={"X-Api-Key": os.environ["HEYGEN_API_KEY"]}
)
data = response.json()
```

### Python (httpx)

```python
import os
import httpx

async with httpx.AsyncClient() as client:
    response = await client.get(
        "https://api.heygen.com/v2/avatars",
        headers={"X-Api-Key": os.environ["HEYGEN_API_KEY"]}
    )
    data = response.json()
```

## Creating a Reusable API Client

### TypeScript

```typescript
class HeyGenClient {
  private baseUrl = "https://api.heygen.com";
  private [REDACTED_SECRET];

  constructor([REDACTED_SECRET]) {
    this.[REDACTED_SECRET];
  }

  async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
    const response = await fetch(`${this.baseUrl}${endpoint}`, {
      ...options,
      headers: {
        "X-Api-Key": this.apiKey,
        "Content-Type": "application/json",
        ...options.headers,
      },
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.message || `HTTP ${response.status}`);
    }

    return response.json();
  }

  get<T>(endpoint: string): Promise<T> {
    return this.request<T>(endpoint);
  }

  post<T>(endpoint: string, body: unknown): Promise<T> {
    return this.request<T>(endpoint, {
      method: "POST",
      body: JSON.stringify(body),
    });
  }
}

// Usage
const client = new HeyGenClient(process.env.HEYGEN_API_KEY!);
const avatars = await client.get("/v2/avatars");
```

## API Response Format

All HeyGen API responses follow this structure:

```typescript
interface ApiResponse<T> {
  error: null | string;
  data: T;
}
```

Successful response example:

```json
{
  "error": null,
  "data": {
    "avatars": [...]
  }
}
```

Error response example:

```json
{
  "error": "Invalid API key",
  "data": null
}
```

## Error Handling

Common authentication errors:

| Status Code | Error | Cause |
|-------------|-------|-------|
| 401 | Invalid API key | API key is missing or incorrect |
| 403 | Forbidden | API key doesn't have required permissions |
| 429 | Rate limit exceeded | Too many requests |

### Handling Errors

```typescript
async function makeRequest(endpoint: string) {
  const response = await fetch(`https://api.heygen.com${endpoint}`, {
    headers: { "X-Api-Key": process.env.HEYGEN_API_KEY! },
  });

  const json = await response.json();

  if (!response.ok || json.error) {
    throw new Error(json.error || `HTTP ${response.status}`);
  }

  return json.data;
}
```

## Rate Limiting

HeyGen enforces rate limits on API requests:
- Standard rate limits apply per API key
- Some endpoints (like video generation) have stricter limits
- Use exponential backoff when receiving 429 errors

```typescript
async function requestWithRetry(
  fn: () => Promise<Response>,
  maxRetries = 3
): Promise<Response> {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fn();

    if (response.status === 429) {
      const waitTime = Math.pow(2, i) * 1000;
      await new Promise((resolve) => setTimeout(resolve, waitTime));
      continue;
    }

    return response;
  }

  throw new Error("Max retries exceeded");
}
```

## Security Best Practices

1. **Never expose API keys in client-side code** - Always make API calls from a backend server
2. **Use environment variables** - Don't hardcode API keys in source code
3. **Rotate keys periodically** - Generate new API keys regularly
4. **Monitor usage** - Check your HeyGen dashboard for unusual activity


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)