---
title: GenPixy API docs
description: 'How to make explainer videos with the GenPixy API and MCP server: keys, endpoints, fields, errors, and agent setup.'
updated: 2026-11-03
fallback_ok: true
---

The GenPixy API turns a topic or a script into a narrated explainer video. You start a video with one call, check it until it is done, and download the files. AI agents can use the same API through [SKILL.md](/api/skill.md) or the [MCP server](#mcp-server).

## Quick start

Base URL: `https://www.genpixy.com/api/v1`. Every call needs the header `Authorization: Bearer $GENPIXY_API_KEY`.

```sh
# 1. Create
curl -s https://www.genpixy.com/api/v1/videos \
  -H "Authorization: Bearer $GENPIXY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: my-first-video" \
  -d '{"prompt":"How black holes form","seconds":60}'

# 2. Check (repeat every 10 s until "status" is "completed")
curl -s https://www.genpixy.com/api/v1/videos/<id> -H "Authorization: Bearer $GENPIXY_API_KEY"

# 3. Download
curl -L -o video.mp4 "https://www.genpixy.com/api/v1/videos/<id>/content?variant=video" \
  -H "Authorization: Bearer $GENPIXY_API_KEY"
```

Using an AI agent? Paste this prompt into it:

```txt
Read https://www.genpixy.com/api/skill.md and make me a 60-second explainer video about how black holes form.
```

## Authentication

- Create a key at [Account → API keys](/account/api-keys). A key looks like `gpx_` followed by 43 letters, digits, `-`, or `_`.
- We show the key only once, when you create it. We store only a fingerprint of it. If you lose it, revoke it and create a new one.
- Send it in every request: `Authorization: Bearer gpx_…`.
- Store it in the environment variable `GENPIXY_API_KEY`. Agents and the examples on this page read it from there.
- Each account can have 10 active keys. Revoke a key at any time; calls with it stop at once, and videos that already started keep going.
- Keys are for servers, scripts, and agents. Do not put a key in a web page: the API sends no CORS headers.

## Use with AI agents

The fastest way: paste this prompt into any agent that can read a web page and run a command (Claude Code, Codex, OpenClaw, Hermes Agent, and others):

```txt
Read https://www.genpixy.com/api/skill.md and make me a 60-second explainer video about how black holes form.
```

To install the skill so your agent always knows GenPixy:

```sh
# Claude Code
mkdir -p ~/.claude/skills/genpixy && curl -fsSL https://www.genpixy.com/api/skill.md -o ~/.claude/skills/genpixy/SKILL.md

# Codex and OpenClaw
mkdir -p ~/.agents/skills/genpixy && curl -fsSL https://www.genpixy.com/api/skill.md -o ~/.agents/skills/genpixy/SKILL.md

# Hermes Agent
hermes skills install https://www.genpixy.com/api/skill.md
```

Files for agents and tools:

| File                                   | What it is                                     |
| -------------------------------------- | ---------------------------------------------- |
| [/api/skill.md](/api/skill.md)         | Agent Skills file (`SKILL.md`, name `genpixy`) |
| [/api/docs.md](/api/docs.md)           | This page as Markdown                          |
| [/api/openapi.json](/api/openapi.json) | OpenAPI 3.1 description of `/api/v1`           |
| `https://www.genpixy.com/api/mcp`      | MCP server (see [MCP server](#mcp-server))     |

## MCP server

GenPixy has a remote MCP (Model Context Protocol) server. Connect it once, and your agent can make videos with tools instead of HTTP calls.

- URL: `https://www.genpixy.com/api/mcp`
- Transport: Streamable HTTP
- Authentication: the header `Authorization: Bearer gpx_…` with your API key

### Connect your client

```sh
# Claude Code
claude mcp add --transport http genpixy https://www.genpixy.com/api/mcp \
  --header "Authorization: Bearer $GENPIXY_API_KEY"

# Codex (reads the key from GENPIXY_API_KEY on every call)
codex mcp add genpixy --url https://www.genpixy.com/api/mcp --bearer-token-env-var GENPIXY_API_KEY
```

Other clients (Cursor, VS Code, Windsurf, and more) take a JSON entry like this. Put your key in place of `gpx_…`:

```json
{
	"mcpServers": {
		"genpixy": {
			"url": "https://www.genpixy.com/api/mcp",
			"headers": { "Authorization": "Bearer gpx_…" }
		}
	}
}
```

### Tools

| Tool           | What it does                                                                                               |
| -------------- | ---------------------------------------------------------------------------------------------------------- |
| `create_video` | Starts a video. Takes the same fields as `POST /api/v1/videos`, plus an optional `idempotency_key`.        |
| `get_video`    | Returns one video (`id`). Call it every 10 seconds until `status` is `completed`, `failed`, or `canceled`. |
| `list_videos`  | Lists your videos, newest first. Pass `after` (the previous `next_cursor`) for the next page.              |
| `get_account`  | Returns your balance, the reserved amount, and the videos in progress.                                     |
| `get_options`  | Returns every option, its default, and the cost of each length and resolution.                             |

Tool results are the same JSON objects as the HTTP API. When a call fails, the result has `isError: true` and the same error object as the HTTP API (see [Errors](#errors)). A completed video has `result.files` (download links) and `app_url` (the video page in GenPixy). Download the files with an HTTP GET and the same `Authorization` header.

## Create a video

### POST /api/v1/videos

```sh
curl -s https://www.genpixy.com/api/v1/videos \
  -H "Authorization: Bearer $GENPIXY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 4f9c2a51-video-1" \
  -d '{"prompt":"How black holes form, for curious teenagers","seconds":60,"orientation":"landscape"}'
```

The body is a JSON object. Unknown fields are refused.

| Field         | Type    | Default      | Values                                                                                                                     |
| ------------- | ------- | ------------ | -------------------------------------------------------------------------------------------------------------------------- |
| `prompt`      | string  | required     | 3 to 5,000 characters: a topic, notes, or a full script. Line breaks and Markdown lists are fine.                          |
| `seconds`     | integer | `60`         | `30`, `60`, `90`, `120`, `180`, `300`, `480`, `600`                                                                        |
| `orientation` | string  | `landscape`  | `landscape` (YouTube), `portrait` (TikTok, Reels, Shorts)                                                                  |
| `resolution`  | string  | `720p`       | `720p`, `1080p` (1.5 times the price of 720p)                                                                              |
| `style`       | string  | `whiteboard` | `whiteboard`, `animate` (cartoon animation), `flat` (Color Board). `GET /api/v1/options` lists the styles you can use now. |
| `language`    | string  | `auto`       | `auto` (narration follows the prompt language, one of 76), `en`, `id`                                                      |
| `voice`       | string  | `male`       | `male`, `female`                                                                                                           |
| `subtitles`   | boolean | `true`       | Word-by-word subtitles on the video                                                                                        |
| `music`       | boolean | `true`       | Background music                                                                                                           |
| `big_board`   | boolean | `false`      | All scenes on one board, with a zoom-out recap at the end                                                                  |
| `zoom_dive`   | boolean | `false`      | The camera flies into an icon when the next scene looks closer at it                                                       |

**Idempotency-Key** (optional header, 1 to 255 printable ASCII characters): send one unique value per video, for example a UUID. If a call fails with a network error or an HTTP 5xx, send the same request again with the same key. You get the same video back and pay only once.

- `201 Created`: a new video. The `Location` header has its path.
- `200 OK` with the header `Idempotent-Replayed: true`: the same key and the same request were sent before; this is that video.
- `409 IDEMPOTENCY_KEY_REUSED`: the same key with a different request. Use a new key for a new video.

The answer is a [Video](#check-a-video) with `status: "queued"`.

## Check a video

### GET /api/v1/videos/{id}

```sh
curl -s https://www.genpixy.com/api/v1/videos/<id> -H "Authorization: Bearer $GENPIXY_API_KEY"
```

| `status`      | Meaning                                                                    |
| ------------- | -------------------------------------------------------------------------- |
| `queued`      | Waiting to start. `queue_position` says how many videos start first.       |
| `in_progress` | Being made. `progress` goes from 0 to 100.                                 |
| `completed`   | Done. `result` has the title, YouTube texts, and file links.               |
| `failed`      | We could not finish it. It costs nothing. `error.message` says what to do. |
| `canceled`    | Canceled. It costs nothing.                                                |

Check every 10 seconds. A video can go back to `queued` for a short time; keep checking. Most short videos are ready in a few minutes.

```json
{
	"id": "01a16c52-6024-7b92-b252-53f87f2303dd",
	"object": "video",
	"status": "completed",
	"progress": 100,
	"queue_position": null,
	"created_at": "2026-11-03T05:20:00.000Z",
	"started_at": "2026-11-03T05:20:01.000Z",
	"completed_at": "2026-11-03T05:22:40.000Z",
	"expires_at": "2027-01-02T05:22:40.000Z",
	"cost": { "units": 16, "display": "…" },
	"request": {
		"prompt": "How black holes form, for curious teenagers",
		"seconds": 60,
		"orientation": "landscape",
		"resolution": "720p",
		"style": "whiteboard",
		"language": "auto",
		"voice": "male",
		"subtitles": true,
		"music": true,
		"big_board": false,
		"zoom_dive": false
	},
	"result": {
		"title": "How Black Holes Form",
		"duration_seconds": 61.4,
		"width": 1280,
		"height": 720,
		"size_bytes": 9123456,
		"youtube_title": "How Do Black Holes Form? Explained Simply",
		"youtube_description": "…",
		"hashtags": ["#space", "#science"],
		"files": {
			"video": "https://www.genpixy.com/api/v1/videos/01a16c52-6024-7b92-b252-53f87f2303dd/content?variant=video",
			"thumbnail": "https://www.genpixy.com/api/v1/videos/01a16c52-6024-7b92-b252-53f87f2303dd/content?variant=thumbnail",
			"subtitles": "https://www.genpixy.com/api/v1/videos/01a16c52-6024-7b92-b252-53f87f2303dd/content?variant=subtitles"
		}
	},
	"error": null,
	"app_url": "https://www.genpixy.com/app/drawgen/01a16c52-6024-7b92-b252-53f87f2303dd"
}
```

`result` is `null` until the video is `completed`. `app_url` opens the video in GenPixy, where you can watch and share it.

## Download files

### GET /api/v1/videos/{id}/content

```sh
curl -fL -o video.mp4 "https://www.genpixy.com/api/v1/videos/<id>/content?variant=video" -H "Authorization: Bearer $GENPIXY_API_KEY"
```

| `variant`         | File              | Type                                  |
| ----------------- | ----------------- | ------------------------------------- |
| `video` (default) | The MP4 video     | `video/mp4` (supports one byte range) |
| `thumbnail`       | The thumbnail     | `image/png`                           |
| `subtitles`       | The subtitle file | `application/x-subrip` (`.srt`)       |

- Before the video is `completed`: `409 VIDEO_NOT_READY`.
- Files are kept for 60 days (`expires_at`). After that: `410 FILE_EXPIRED`.

## List videos

### GET /api/v1/videos

```sh
curl -s https://www.genpixy.com/api/v1/videos -H "Authorization: Bearer $GENPIXY_API_KEY"
```

Returns `{"object": "list", "data": [...], "next_cursor": "…"}` with 24 videos per page, newest first. For the next page, add `?after=<next_cursor>`. `next_cursor` is `null` on the last page. The list includes videos you made on the website.

## Account and options

### GET /api/v1/account

```json
{
	"object": "account",
	"email": "you@example.com",
	"balance": { "units": 184, "display": "…" },
	"reserved": { "units": 16, "display": "…" },
	"active_videos": 1,
	"max_active_videos": 2,
	"top_up_url": "https://www.genpixy.com/account/billing"
}
```

### GET /api/v1/options

Returns every option of `POST /api/v1/videos`, the defaults, and `costs`: the cost of each length and resolution for your account.

**Amounts** look like `{"units": 16, "display": "…"}`. `units` is for code (compare and add them). `display` is the same text your GenPixy app shows for this amount, so show `display` to people.

## Prices and limits

- Each video uses your GenPixy balance, at the same price as the app. You pay only for finished videos: failed and canceled videos cost nothing.
- Read the exact cost for your account from `GET /api/v1/options`. Top up at [Account → Billing](/account/billing).
- API videos never have a watermark.
- Limits: 2 videos in progress at a time, 5 new videos per minute (shared with the website), and 120 requests per minute per key.

## Errors

Every error has the same shape:

```json
{
	"error": {
		"code": "INSUFFICIENT_BALANCE",
		"message": "Your balance is too low for this video. …",
		"request_id": "01a19c6f-b20b-7693-bcd4-bd5eb4dded2a"
	}
}
```

`message` says what happened and what to do; show it to people. Quote `request_id` when you contact support.

| HTTP | `code`                   | What to do                                                                     |
| ---- | ------------------------ | ------------------------------------------------------------------------------ |
| 400  | `INVALID_REQUEST`        | Fix the fields listed in `issues`.                                             |
| 401  | `UNAUTHORIZED`           | The key is missing, wrong, or revoked. Create a new key.                       |
| 402  | `INSUFFICIENT_BALANCE`   | Top up at `top_up_url`. `needed` and `available` are amounts.                  |
| 403  | `ACCOUNT_SUSPENDED`      | Contact support.                                                               |
| 403  | `ACCOUNT_NOT_READY`      | Open https://www.genpixy.com/app once, then try again.                         |
| 404  | `NOT_FOUND`              | No video with this id in your account, or the path does not exist.             |
| 405  | `METHOD_NOT_ALLOWED`     | Use the method in the `allow` header.                                          |
| 409  | `IDEMPOTENCY_KEY_REUSED` | Use a new `Idempotency-Key` for a new video.                                   |
| 409  | `VIDEO_NOT_READY`        | Wait until the video is `completed`.                                           |
| 410  | `FILE_EXPIRED`           | Files are kept for 60 days. Make the video again.                              |
| 413  | `PAYLOAD_TOO_LARGE`      | Keep the prompt under 5,000 characters.                                        |
| 415  | `UNSUPPORTED_MEDIA_TYPE` | Send JSON with `Content-Type: application/json`.                               |
| 422  | `PROMPT_REFUSED`         | GenPixy cannot make a video about this topic. Try a different topic.           |
| 429  | `TOO_MANY_ACTIVE_VIDEOS` | 2 videos are in progress. Wait until one finishes.                             |
| 429  | `RATE_LIMITED`           | Wait `retry_after_seconds` (also in the `retry-after` header), then try again. |
| 500  | `INTERNAL_ERROR`         | Try again with the same `Idempotency-Key`. Quote `request_id` if it repeats.   |
| 503  | `TRY_AGAIN`              | Try again in 30 seconds with the same `Idempotency-Key`. Nothing was charged.  |
| 503  | `SERVICE_UNAVAILABLE`    | Try again later.                                                               |

## Changelog

- 2026-11-03: v1 released, with the MCP server.
