PSM Video Generation API
Production-grade video generation via REST API. Generate videos from text, images, or audio using state-of-the-art models.
Base URL: https://api.purplesquirrelmedia.io
Authentication
All API requests require a Bearer token in the Authorization header:
curl https://api.purplesquirrelmedia.io/v1/models \ -H "Authorization: Bearer psm_live_YOUR_API_KEY"
API keys are prefixed with psm_live_ for production and psm_test_ for testing.
Errors
The API returns standard HTTP status codes with JSON error bodies:
{
"error": {
"message": "Human-readable description",
"code": "machine_readable_code"
}
}
| Status | Code | Description |
|---|---|---|
| 400 | Various | Invalid request parameters |
| 401 | auth_required | Missing or invalid API key |
| 402 | limit_exceeded | Monthly generation limit reached |
| 404 | not_found | Resource not found |
| 429 | rate_limit_exceeded | Too many requests |
| 500 | internal_error | Server error |
Rate Limits
Requests are rate-limited per API key per minute. Check X-RateLimit-Limit and X-RateLimit-Remaining headers.
| Plan | Requests/min | Generations/month |
|---|---|---|
| Free | 5 | 10 |
| Starter | 30 | 200 |
| Pro | 100 | 800 |
| Enterprise | 500 | Custom |
Create Generation
Submit a video generation job. Returns immediately with a job ID. Poll the status endpoint or use webhooks for completion.
Request Body
| Parameter | Type | Description |
|---|---|---|
| model | string optional | Model to use. Default: wan-2.7 |
| prompt | string required* | Text description of the video to generate |
| negative_prompt | string optional | What to avoid in the generation |
| image_url | string required* | Source image URL (for image-to-video) |
| mode | string optional | text-to-video | image-to-video | video-to-video |
| duration | integer optional | Duration in seconds (default: 5, max varies by model) |
| resolution | string optional | 480p | 720p | 1080p (default: 720p) |
| aspect_ratio | string optional | 16:9 | 9:16 | 1:1 (default: 16:9) |
| webhook_url | string optional | URL to receive completion/failure events |
Example
curl -X POST https://api.purplesquirrelmedia.io/v1/generations \
-H "Authorization: Bearer psm_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "wan-2.7",
"prompt": "Aerial drone shot over misty mountains at golden hour",
"duration": 5,
"resolution": "720p",
"webhook_url": "https://your-app.com/webhook"
}'
Response (201)
{
"id": "gen_abc123",
"status": "queued",
"model": "wan-2.7",
"mode": "text-to-video",
"prompt": "Aerial drone shot over misty mountains at golden hour",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9",
"video_url": null,
"created_at": "2026-04-09T12:00:00.000Z"
}
Get Generation
Retrieve the status and result of a generation job. Poll this endpoint until status is completed or failed.
Response (200)
{
"id": "gen_abc123",
"status": "completed",
"model": "wan-2.7",
"video_url": "https://api.purplesquirrelmedia.io/v1/videos/TOKEN",
"created_at": "2026-04-09T12:00:00.000Z",
"completed_at": "2026-04-09T12:01:30.000Z"
}
Status values: queued → processing → completed | failed | cancelled
List Generations
List your generation jobs, newest first. Filter by status.
Cancel Generation
Cancel a queued or processing generation. Cannot cancel completed/failed jobs.
List Models
List all available video generation models with their capabilities and pricing.
Webhook Events
If you provide a webhook_url when creating a generation, PSM will POST to that URL when the job completes or fails.
generation.completed
{
"event": "generation.completed",
"data": {
"id": "gen_abc123",
"status": "completed",
"model": "wan-2.7",
"video_url": "https://api.purplesquirrelmedia.io/v1/videos/TOKEN",
"prompt": "...",
"duration": 5
}
}
generation.failed
{
"event": "generation.failed",
"data": {
"id": "gen_abc123",
"status": "failed",
"model": "wan-2.7",
"error": { "message": "...", "code": "generation_failed" }
}
}
Verifying Webhook Signatures
Each webhook includes an X-PSM-Signature header for verification:
X-PSM-Signature: t=1712700000,v1=5a3c1e...
To verify: compute HMAC-SHA256(timestamp + "." + body) using your webhook signing key and compare to the v1 value.
Available Models
[
{
"id": "wan-2.7",
"name": "Wan 2.7",
"provider": "fal",
"modes": [
"text-to-video",
"image-to-video"
],
"max_duration": 10,
"resolutions": [
"720p",
"1080p"
],
"aspect_ratios": [
"16:9",
"9:16",
"1:1"
],
"cost_per_second": 0.1
},
{
"id": "ltx-video",
"name": "LTX Video 13B",
"provider": "fal",
"modes": [
"text-to-video",
"image-to-video"
],
"max_duration": 60,
"resolutions": [
"480p",
"720p"
],
"aspect_ratios": [
"16:9",
"9:16",
"1:1",
"4:3"
],
"cost_per_second": 0.02
},
{
"id": "cogvideox",
"name": "CogVideoX-5B",
"provider": "fal",
"modes": [
"text-to-video",
"image-to-video",
"video-to-video"
],
"max_duration": 10,
"resolutions": [
"480p",
"720p"
],
"aspect_ratios": [
"16:9",
"1:1"
],
"cost_per_second": 0.02
}
]
Quick Reference
| Model | Modes | Max Duration | Resolutions | Cost |
|---|---|---|---|---|
| wan-2.7 | text, image | 10s | 720p, 1080p | $0.10/sec |
| ltx-video | text, image | 60s | 480p, 720p | $0.02/sec |
| cogvideox | text, image, video | 10s | 480p, 720p | $0.02/sec |