OpenAI Videos API
The Poe API supports the OpenAI Video Generation API format, enabling AI-powered video creation through the same OpenAI SDK you already know. Just point it at Poe.
Key capabilities:
- Text-to-video and image-to-video generation
- Video remix (re-style an existing video with a new prompt)
- Video extension (continue a completed video)
- Access video models (Sora, Veo) through a single Poe API key
- Asynchronous workflow with polling
Video generation is asynchronous. You submit a request, poll for completion, then download the result.
Quick Start
Create a video, poll until it completes, and download the result:
# pip install openai
import os, time, openai
client = openai.OpenAI(
api_key=os.getenv("POE_API_KEY"), # https://poe.com/api/keys
base_url="https://api.poe.com/v1",
)
# Submit video generation request
video = client.videos.create(
model="Sora-2", # Poe bot name
prompt="A golden retriever running through a sunflower field at sunset",
seconds=8,
size="1280x720",
)
# Poll until complete
while video.status in ("queued", "in_progress"):
time.sleep(5)
video = client.videos.retrieve(video_id=video.id)
print(f"Video completed: {video.id}")
# Download the video
content = client.videos.download_content(video_id=video.id)
with open("output.mp4", "wb") as f:
f.write(content.content)
print("Saved to output.mp4")Or use the convenience helper that combines create + poll:
# Blocks until video is complete
video = client.videos.create_and_poll(
model="Sora-2",
prompt="A golden retriever running through a sunflower field at sunset",
seconds=8,
size="1280x720",
)
print(f"Video completed: {video.id}")
content = client.videos.download_content(video_id=video.id)
with open("output.mp4", "wb") as f:
f.write(content.content)# 1. Create the video
curl "https://api.poe.com/v1/videos" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $POE_API_KEY" \
-d '{
"model": "Sora-2",
"prompt": "A golden retriever running through a sunflower field at sunset",
"seconds": 8,
"size": "1280x720"
}'
# 2. Poll for completion (replace VIDEO_ID with the id from step 1)
curl "https://api.poe.com/v1/videos/VIDEO_ID" \
-H "Authorization: Bearer $POE_API_KEY"
# 3. Download the video (once status is "completed")
curl "https://api.poe.com/v1/videos/VIDEO_ID/content" \
-H "Authorization: Bearer $POE_API_KEY" \
--output output.mp4Image-to-Video
Generate a video from a reference image:
import os, openai
client = openai.OpenAI(
api_key=os.getenv("POE_API_KEY"),
base_url="https://api.poe.com/v1",
)
video = client.videos.create_and_poll(
model="Sora-2",
prompt="The dog starts running and jumps over a log",
input_reference=open("image.jpg", "rb"),
)
content = client.videos.download_content(video_id=video.id)
with open("output.mp4", "wb") as f:
f.write(content.content)curl "https://api.poe.com/v1/videos" \
-H "Authorization: Bearer $POE_API_KEY" \
-F "model=Sora-2" \
-F "prompt=The dog starts running and jumps over a log" \
-F "[email protected]"Remix
Re-style an existing video with a new prompt:
import os, time, openai
client = openai.OpenAI(
api_key=os.getenv("POE_API_KEY"),
base_url="https://api.poe.com/v1",
)
remix = client.videos.remix(
video_id=video.id,
prompt="Transform into an anime-style animation",
)
# Poll until complete
while remix.status in ("queued", "in_progress"):
time.sleep(5)
remix = client.videos.retrieve(video_id=remix.id)
content = client.videos.download_content(video_id=remix.id)
with open("remix.mp4", "wb") as f:
f.write(content.content)# Replace VIDEO_ID with the source video's id
curl "https://api.poe.com/v1/videos/VIDEO_ID/remix" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $POE_API_KEY" \
-d '{
"prompt": "Transform into an anime-style animation"
}'Note: The model is inherited from the source video. You do not need to specify a
modelparameter for remix requests.
Extend a Video
Continue a completed video with additional content:
import os, time, openai
client = openai.OpenAI(
api_key=os.getenv("POE_API_KEY"),
base_url="https://api.poe.com/v1",
)
extension = client.post(
"/videos/extensions",
body={
"video": {"id": video.id},
"prompt": "The dog continues running and leaps into a lake",
"seconds": 8,
},
cast_to=openai.types.video.Video,
)
# Poll until complete
while extension.status in ("queued", "in_progress"):
time.sleep(5)
extension = client.videos.retrieve(video_id=extension.id)
content = client.videos.download_content(video_id=extension.id)
with open("extended.mp4", "wb") as f:
f.write(content.content)curl "https://api.poe.com/v1/videos/extensions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $POE_API_KEY" \
-d '{
"video": {"id": "VIDEO_ID"},
"prompt": "The dog continues running and leaps into a lake",
"seconds": 8
}'Note: The source video must be in
completedstatus. The model is inherited from the source video. Thesecondsparameter is optional and controls the extension duration. OpenAI limits the total duration (original + extensions) to 120 seconds for Sora models.
Downloading Content
Download the full video, a thumbnail, or a spritesheet:
import os, openai
client = openai.OpenAI(
api_key=os.getenv("POE_API_KEY"),
base_url="https://api.poe.com/v1",
)
# Download the full video (default)
video_content = client.videos.download_content(video_id=video.id)
with open("video.mp4", "wb") as f:
f.write(video_content.content)
# Download the thumbnail
thumbnail = client.videos.download_content(video_id=video.id, variant="thumbnail")
with open("thumbnail.webp", "wb") as f:
f.write(thumbnail.content)
# Download the spritesheet
spritesheet = client.videos.download_content(video_id=video.id, variant="spritesheet")
with open("spritesheet.jpg", "wb") as f:
f.write(spritesheet.content)# Download the full video (default)
curl "https://api.poe.com/v1/videos/VIDEO_ID/content" \
-H "Authorization: Bearer $POE_API_KEY" \
--output video.mp4
# Download the thumbnail
curl "https://api.poe.com/v1/videos/VIDEO_ID/content?variant=thumbnail" \
-H "Authorization: Bearer $POE_API_KEY" \
--output thumbnail.webp
# Download the spritesheet
curl "https://api.poe.com/v1/videos/VIDEO_ID/content?variant=spritesheet" \
-H "Authorization: Bearer $POE_API_KEY" \
--output spritesheet.jpgContent variants:
| Variant | Content-Type | Description |
|---|---|---|
| (default) | video/mp4 | Full video file |
| thumbnail | image/webp | Preview thumbnail |
| spritesheet | image/jpeg | Spritesheet of frames |
Detailed API Reference
Endpoints
| Method | Path | Description |
|---|---|---|
POST | /v1/videos | Create a new video |
GET | /v1/videos/{video_id} | Retrieve video status |
GET | /v1/videos/{video_id}/content | Download video content |
POST | /v1/videos/{video_id}/remix | Remix an existing video |
POST | /v1/videos/extensions | Extend a completed video |
Create Request Fields
| Field | Required | Description |
|---|---|---|
model | Yes | Poe bot name (e.g. Sora-2, Veo-2) |
prompt | Yes | Text description of the video to generate |
seconds | No | Duration in seconds (default varies by model) |
size | No | Resolution as WIDTHxHEIGHT (e.g. 1280x720) |
input_reference | No | Reference image file (multipart form upload) |
input_image | No | Base64-encoded reference image (JSON body) |
Remix Request Fields
| Field | Required | Description |
|---|---|---|
prompt | Yes | New prompt describing the desired style |
The model is inherited from the source video. No
modelparameter is needed.
Extension Request Fields
| Field | Required | Description |
|---|---|---|
video | Yes | Object with id of the source video (e.g. {"id": "video_abc123"}) |
prompt | Yes | Text description of the continuation |
seconds | No | Duration of the extension in seconds |
The model is inherited from the source video. No
modelparameter is needed.
Video Response Fields
| Field | Description |
|---|---|
id | Unique video identifier |
object | Always "video" |
status | queued, in_progress, completed, failed |
created_at | Unix timestamp of creation |
completed_at | Unix timestamp of completion (null if not yet complete) |
expires_at | Unix timestamp when the video content expires |
model | Model used for generation |
seconds | Duration of the video in seconds |
size | Resolution as WIDTHxHEIGHT |
progress | Generation progress (0-100) |
remixed_from_video_id | ID of the source video (for remixes) |
error | Error details (if status is failed) |
usage | Token/point usage information |
Supported Models
| Poe Bot Name | Provider | Max Duration | Features |
|---|---|---|---|
| Sora-2 | OpenAI | 20 seconds | Create, status, download, remix, extend |
| Sora-2-Pro | OpenAI | 20 seconds | Create, status, download, remix, extend (1080p) |
| Veo-2 | Google Vertex AI | 8 seconds | Create, status, download |
| Veo-3 | Google Vertex AI | 8 seconds | Create, status, download |
| Veo-3-Fast | Google Vertex AI | 8 seconds | Create, status, download |
| Veo-3.1 | Google Vertex AI | 8 seconds | Create, status, download |
| Veo-3.1-Fast | Google Vertex AI | 8 seconds | Create, status, download |
Note: Default duration when
secondsis omitted varies by provider: 4 seconds for OpenAI models, 8 seconds for Vertex AI models.
Known Issues & Limitations
- Asynchronous only - Video generation does not support streaming. You must poll for completion.
- Remix and extension: Sora models only - Veo models (Vertex AI) do not support remix or extend operations.
- Extension requires completed source video - The source video must have
status: "completed"before it can be extended. - Private bots not supported - Only public bots can be accessed through the API.
- Characters and video editing not available - The characters and storyboard editing features from OpenAI's platform are not available on Poe.
- Default resolution is 720x1280 (portrait) - Specify
sizeexplicitly if you need a different aspect ratio.
Error Handling
Error responses follow the same format as the OpenAI Compatible API:
{
"error": {
"code": 401,
"type": "authentication_error",
"message": "Invalid API key",
"metadata": {}
}
}| HTTP Code | Type | When It Happens |
|---|---|---|
| 400 | invalid_request_error | Malformed JSON, missing required fields |
| 401 | authentication_error | Bad or expired API key |
| 402 | insufficient_credits | Point balance is zero |
| 404 | not_found | Video ID does not exist |
| 429 | rate_limit_error | Rate limit exceeded |
| 500 | provider_error | Provider-side issues |
Retry tips:
- Respect the
Retry-Afterheader on 429 responses - Use exponential backoff starting at 250ms with jitter
Pricing & Availability
All Poe subscribers can use their existing subscription points with the API at no additional cost.
This means you can seamlessly transition between the web interface and API without worrying about separate billing structures or additional fees. Your regular monthly point allocation works exactly the same way whether you're chatting directly on Poe or accessing bots programmatically through the API.
If your Poe subscription is not enough, you can now purchase add-on points to get as much access as your application requires. Our intent in pricing these points is to charge the same amount for model access that underlying model providers charge. Any add-on points you purchase can be used with any model or bot on Poe and work across both the API and Poe chat on web, iOS, Android, Mac, and Windows.
Support
Feel free to reach out to support if you come across some unexpected behavior when using our API or have suggestions for future improvements.