Introduction
Welcome to the BeamGo API documentation. Our API allows you to integrate powerful AI video generation features directly into your applications.
Core Concepts
Before you begin, it's important to understand a few core concepts about the API's design:
- Asynchronous Nature: Video generation can take time. Our API is asynchronous. When you submit a request, we immediately return a
job_id. You then use this ID to check the job's status until it's complete. - Workflows: A "workflow" defines a type of task you can perform, such as
text_to_video. Each workflow has its own parameters and credit cost. - Jobs: A "job" represents a single, specific task you've requested, like generating a video from a particular prompt.
- Webhooks: Instead of constantly checking a job's status (polling), we highly recommend using webhooks to receive a notification on your server as soon as a job is finished.
https://api.yourdomain.com
Authentication
All API requests must be authenticated. The API uses API Keys to identify your account.
To authenticate, include your API Key in the X-API-Key header of every request.
X-API-Key: ndfy_your_secret_api_key_here
You can generate and manage your API Keys from the "API" section of your dashboard.
Workflows
Workflows are the main entry points for creating content. The first step is usually to see which workflows are available.
List Available Workflows
Retrieves a list of all available workflows, their descriptions, and their cost in credits.
Example Request
curl "https://api.yourdomain.com/workflows" -H "X-API-Key: ndfy_your_api_key_here"import requests
API_KEY = "ndfy_your_api_key_here"
API_URL = "https://api.yourdomain.com/workflows"
response = requests.get(API_URL, headers={"X-API-Key": API_KEY})
if response.ok:
print(response.json())
else:
print(f"Error: {response.status_code} - {response.text}")Example Response
{
"workflows": [
{
"id": "text_to_video",
"description": "Generate a video from a text prompt and aspect ratio.",
"cost": 25
},
{
"id": "image_to_video",
"description": "Animate an image, optionally guided by a text prompt.",
"cost": 30
}
]
}
Run Text-to-Video Workflow
Submits a job to generate a video from a text prompt. The order of fields in the JSON body does not matter.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Detailed description of the video content. Max 1000 characters. |
aspect_ratio | string | Yes | Aspect ratio. Allowed: "1:1", "landscape (16:9)", "portrait (9:16)". |
seed | integer | No | A number for reproducibility. Default: 0 (which means random). |
Example Request
curl -X POST "https://api.yourdomain.com/workflows/text-to-video/run" -H "Content-Type: application/json" -H "X-API-Key: ndfy_your_api_key_here" -d '{
"prompt": "A majestic eagle soaring through clouds",
"aspect_ratio": "landscape (16:9)",
"seed": 42
}'import requests
API_KEY = "ndfy_your_api_key_here"
API_URL = "https://api.yourdomain.com/workflows/text-to-video/run"
payload = {
"prompt": "A majestic eagle soaring through clouds",
"aspect_ratio": "landscape (16:9)",
"seed": 42
}
response = requests.post(API_URL, headers={"X-API-Key": API_KEY}, json=payload)
# On success (202), response.json() will be:
# {"job_id": "...", "message": "..."}
print(response.status_code, response.json())// Using node-fetch: npm install node-fetch
import fetch from 'node-fetch';
const payload = {
prompt: "A majestic eagle soaring through clouds",
aspect_ratio: "landscape (16:9)",
seed: 42
};
const response = await fetch("...", {
method: 'POST',
headers: { 'X-API-Key': '...', 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
const data = await response.json();
console.log(response.status, data);Example Response
{
"job_id": "123e4567-e89b-12d3-a456-426614174000",
"message": "Text-to-Video job accepted."
}
Run Image-to-Video Workflow
Submits a job to animate an image. This endpoint uses multipart/form-data.
Request Body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
input_image | file | Yes | Image file to animate (PNG, JPG, WEBP). Max size: 1MB. |
prompt | string | No | Optional text prompt to guide the animation. |
seed | integer | No | A number for reproducibility. Default: 0 (which means random). |
Example Request
curl -X POST "https://api.yourdomain.com/workflows/image-to-video/run" -H "X-API-Key: ndfy_your_api_key_here" -F "input_image=@path/to/my_image.png" -F "prompt=make the character's eyes glow" -F "seed=12345"import requests
API_KEY = "ndfy_your_api_key_here"
API_URL = "https://api.yourdomain.com/workflows/image-to-video/run"
data = {
"prompt": "make the character's eyes glow",
"seed": 12345
}
with open("my_image.png", "rb") as image_file:
files = {"input_image": image_file}
response = requests.post(API_URL, headers={"X-API-Key": API_KEY}, data=data, files=files)
print(response.status_code, response.json())// Using 'form-data': npm install form-data
import FormData from 'form-data';
import fs from 'fs';
import fetch from 'node-fetch';
const form = new FormData();
form.append('input_image', fs.createReadStream('./my_image.png'));
form.append('prompt', "make the character's eyes glow");
form.append('seed', 12345);
const response = await fetch("...", {
method: 'POST',
headers: { 'X-API-Key': '...' }, // Content-Type is set automatically
body: form
});
const data = await response.json();
console.log(response.status, data);Example Response
{
"job_id": "3e456712-e89b-12d3-a456-426614174001",
"message": "Image-to-Video job accepted."
}
Jobs
Endpoints for managing and retrieving information about your generation jobs.
Get Job Status
Retrieves the current status, progress, and result of a specific job.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | UUID | The unique identifier of the job. |
Example Request
curl "https://api.yourdomain.com/jobs/123e4567-e89b-12d3-a456-426614174000/status" -H "X-API-Key: ndfy_your_api_key_here"import requests
API_KEY = "ndfy_your_api_key_here"
JOB_ID = "123e4567-e89b-12d3-a456-426614174000"
API_URL = f"https://api.yourdomain.com/jobs/{JOB_ID}/status"
response = requests.get(API_URL, headers={"X-API-Key": API_KEY})
print(response.json())Response Body
The response contains the full job object. When status is COMPLETED, result_video_url will contain a temporary, pre-signed URL to the output file.
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"status": "COMPLETED",
"progress": 100,
"result_video_url": "https://s3.your-region.amazonaws.com/...",
"error_message": null,
"credits_cost": 25,
"credits_deducted": true,
"created_at": "2024-05-21T10:30:00Z",
"updated_at": "2024-05-21T10:35:00Z",
"source": "api_key",
"engine_workflow": "text_to_video",
"parameters": { "prompt": "...", "aspect_ratio": "..." }
}
Possible Status Values
PENDING: Job is in the queue, waiting to be processed.PROCESSING: Job is actively being processed by a worker.COMPLETED: Job finished successfully. The result is available.FAILED: Job failed. Check theerror_messagefield for details.
Get Download URL
Retrieves only the download URL for a completed job. This is a lightweight alternative to the full status endpoint if you only need the result URL.
Example Request
curl "https://api.yourdomain.com/jobs/123e4567-e89b-12d3-a456-426614174000/download" -H "X-API-Key: ndfy_your_api_key_here"import requests
API_KEY = "ndfy_your_api_key_here"
JOB_ID = "123e4567-e89b-12d3-a456-426614174000"
API_URL = f"https://api.yourdomain.com/jobs/{JOB_ID}/download"
response = requests.get(API_URL, headers={"X-API-Key": API_KEY})
print(response.json())Responses
{
"download_url": "https://s3.your-region.amazonaws.com/..."
}
{
"detail": "Video not ready. Current status: PROCESSING"
}
List Jobs
Returns a paginated list of your most recent jobs.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 10 | Number of jobs to return (1-50). |
offset | integer | 0 | Number of jobs to skip for pagination. |
Example Request
# Gets jobs 11 through 20
curl "https://api.yourdomain.com/jobs?limit=10&offset=10" -H "X-API-Key: ndfy_your_api_key_here"import requests
API_KEY = "ndfy_your_api_key_here"
API_URL = "https://api.yourdomain.com/jobs"
params = {"limit": 10, "offset": 10}
response = requests.get(API_URL, headers={"X-API-Key": API_KEY}, params=params)
# The total number of jobs is in the response headers
total_count = response.headers.get("X-Total-Count")
print(f"Total jobs: {total_count}")
print(response.json())Response Headers
The response includes an X-Total-Count header indicating the total number of jobs for your account, which is useful for building pagination controls.
Delete a Job
Deletes a job. This action is irreversible and will also delete the associated result file from storage. You can only delete jobs that are in a terminal state (COMPLETED, FAILED) or PENDING.
PROCESSING.
Example Request
# Use -i to see the status code in the response headers
curl -X DELETE -i "https://api.yourdomain.com/jobs/123e4567-e89b-12d3-a456-426614174000" -H "X-API-Key: ndfy_your_api_key_here"import requests
API_KEY = "ndfy_your_api_key_here"
JOB_ID = "123e4567-e89b-12d3-a456-426614174000"
API_URL = f"https://api.yourdomain.com/jobs/{JOB_ID}"
response = requests.delete(API_URL, headers={"X-API-Key": API_KEY})
if response.status_code == 204:
print("Job deleted successfully.")
else:
print(f"Error: {response.status_code} - {response.text}")Response
A successful deletion returns a 204 No Content status code with no body.
Webhooks
Webhooks are the recommended way to get notified about job status changes. Instead of polling for status, you can provide a URL and we will send a POST request to it when an event occurs.
Webhook Events
You can subscribe to the following events:
job.completed: Triggered when a job finishes successfully.job.failed: Triggered when a job fails.
Webhook Payload
All webhook requests are sent with a JSON body containing the following structure:
{
"id": "whk_1684678800.12345",
"event": "job.completed",
"created": "2024-05-21T11:00:00Z",
"data": {
"job_id": "123e4567-e89b-12d3-a456-426614174000",
"status": "COMPLETED",
"workflow": "text_to_video",
"created_at": "2024-05-21T10:55:00Z",
"completed_at": "2024-05-21T11:00:00Z",
"result_url": "https://s3.your-region.amazonaws.com/...",
"error_message": null,
"credits_cost": 25,
"credits_deducted": true
}
}
Verifying Signatures
To ensure that a webhook request genuinely came from us, we include a signature in the X-Webhook-Signature header. You should verify this signature using your webhook's secret token.
import hmac
import hashlib
from fastapi import Request, HTTPException, Depends
WEBHOOK_SECRET = "whsec_your_secret_token_here"
async def verify_signature(request: Request):
signature_header = request.headers.get("X-Webhook-Signature")
if not signature_header:
raise HTTPException(status_code=400, detail="Missing X-Webhook-Signature header")
try: sig_type, signature = signature_header.split("=", 1)
except ValueError: raise HTTPException(status_code=400, detail="Invalid signature format")
if sig_type != "sha256": raise HTTPException(status_code=400, detail="Unsupported signature type")
payload = await request.body()
expected_signature = hmac.new(WEBHOOK_SECRET.encode(), payload, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected_signature, signature):
raise HTTPException(status_code=401, detail="Invalid signature")
return True
# Usage: @app.post("/your-webhook-url", dependencies=[Depends(verify_signature)])
# async def handle_webhook(request: Request):
# webhook_data = await request.json() ...
const crypto = require('crypto');
const express = require('express');
// Middleware to verify the signature
const verifySignature = (req, res, next) => {
const signature = req.headers['x-webhook-signature'];
if (!signature) return res.status(400).send('Missing signature');
const [sigType, sig] = signature.split('=');
if (sigType !== 'sha256') return res.status(400).send('Unsupported signature type');
const WEBHOOK_SECRET = 'whsec_your_secret_token_here';
const expectedSignature = crypto.createHmac('sha256', WEBHOOK_SECRET).update(req.body).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expectedSignature), Buffer.from(sig))) {
return res.status(401).send('Invalid signature');
}
next();
};
const app = express();
// Use express.raw() to get the raw body, required for signature verification
app.post('/your-webhook-url', express.raw({ type: 'application/json' }), verifySignature, (req, res) => {
const webhook_data = JSON.parse(req.body.toString());
console.log('Received event:', webhook_data.event);
res.status(200).send({ received: true });
});
Webhook Management Endpoints
Create Webhook
Creates a new webhook endpoint. A maximum of 10 webhooks are allowed per user.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
url | string (URL) | Yes | The HTTPS URL to receive webhook events. |
events | array[string] | Yes | Array of events to subscribe to (e.g., ["job.completed", "job.failed"]). |
description | string | No | An optional description for your webhook. |
Example Request
curl -X POST "https://api.yourdomain.com/webhooks" -H "X-API-Key: ndfy_your_api_key_here" -H "Content-Type: application/json" -d '{
"url": "https://myapp.com/api/ai-video-webhook",
"events": ["job.completed", "job.failed"],
"description": "Production notifications"
}'import requests
payload = {
"url": "https://myapp.com/api/ai-video-webhook",
"events": ["job.completed", "job.failed"],
"description": "Production notifications"
}
response = requests.post(
"https://api.yourdomain.com/webhooks",
headers={"X-API-Key": "..."},
json=payload
)
print(response.json())Example Response (Success)
The secret_token is only returned on creation. Save it immediately.
{
"id": "e4a7a2a7-12d4-4f4c-83de-724f33a8b4a5",
"url": "https://myapp.com/api/ai-video-webhook",
"events": ["job.completed", "job.failed"],
"description": "Production notifications",
"is_active": true,
"created_at": "2024-05-21T12:00:00Z",
"secret_token": "whsec_..."
}
List Webhooks
Lists all of your currently configured webhooks. The secret token is not returned.
Example Request
curl "https://api.yourdomain.com/webhooks" -H "X-API-Key: ..."import requests
response = requests.get("https://api.yourdomain.com/webhooks", headers={"X-API-Key": "..."})
print(response.json())Delete Webhook
Deletes the webhook configuration with the specified ID.
Example Request
curl -X DELETE "https://api.yourdomain.com/webhooks/e4a7a2a7-12d4-4f4c-83de-724f33a8b4a5" -H "X-API-Key: ..."import requests
WEBHOOK_ID = "e4a7a2a7-12d4-4f4c-83de-724f33a8b4a5"
response = requests.delete(
f"https://api.yourdomain.com/webhooks/{WEBHOOK_ID}",
headers={"X-API-Key": "..."}
)
print(f"Status Code: {response.status_code}") # Expect 204 for successTest Webhook
Sends a test job.completed event to the specified webhook URL. The request body must be empty.
Example Request
curl -X POST "https://api.yourdomain.com/webhooks/e4a7a2a7-12d4-4f4c-83de-724f33a8b4a5/test" -H "X-API-Key: ..."import requests
WEBHOOK_ID = "e4a7a2a7-12d4-4f4c-83de-724f33a8b4a5"
response = requests.post(
f"https://api.yourdomain.com/webhooks/{WEBHOOK_ID}/test",
headers={"X-API-Key": "..."}
)
print(response.status_code, response.json())Example Response
{
"message": "Test webhook dispatch initiated. Check your endpoint for the payload.",
"test_payload": {
"job_id": "...", "status": "COMPLETED", ...
}
}
Account
Endpoints related to your account information.
Get User Profile
Retrieves your full profile, including your current plan and credit balances. This is useful for programmatically checking your available credits.
Example Request
curl "https://api.yourdomain.com/users/me/profile" -H "X-API-Key: ..."import requests
response = requests.get("https://api.yourdomain.com/users/me/profile", headers={"X-API-Key": "..."})
print(response.json())Response Body
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"username": "api_user_1",
"plan_id": "pro",
"created_at": "2024-05-20T12:00:00Z",
"monthly_credits_allowance": 10000,
"monthly_credits_balance": 8500,
"purchased_credits_balance": 500,
"reserved_credits": 55,
"current_period_end": "2024-06-20T12:00:00Z",
"next_plan_id": null,
"available_credits": 8945
}
Rate Limits
To ensure platform stability, we apply several types of rate limits. Exceeding these limits will result in a 429 Too Many Requests error.
Concurrent Jobs
This is the number of jobs you can have in PENDING or PROCESSING status at the same time.
| Plan | Concurrent Jobs |
|---|---|
| Free | 2 |
| Basic | 4 |
| Pro | 8 |
Temporal Limits
These limits control the number of jobs you can submit over a period of time.
| Plan | Hourly Limit | Daily Limit |
|---|---|---|
| Free | 10 | 50 |
| Basic | 100 | 500 |
| Pro | 500 | 2500 |
Error Codes
The API uses standard HTTP status codes to indicate the success or failure of a request.
| Code | Status | Meaning |
|---|---|---|
200 OK | Success | The request was successful. |
202 Accepted | Success | The job was accepted for processing. |
204 No Content | Success | The request was successful, and there is no content to return (e.g., after a DELETE). |
400 Bad Request | Client Error | The request was malformed. Check your parameters, JSON body, or file uploads. This can also be triggered by our content moderation service. |
401 Unauthorized | Client Error | Authentication failed. Check that your X-API-Key is correct and valid. |
402 Payment Required | Client Error | You do not have enough credits to perform this action. |
404 Not Found | Client Error | The requested resource (e.g., a job) could not be found. |
413 Payload Too Large | Client Error | The uploaded file exceeds the maximum allowed size (1MB). |
429 Too Many Requests | Client Error | You have exceeded a rate limit (e.g., too many concurrent jobs or too many requests per hour/day). |
500 Internal Server Error | Server Error | Something went wrong on our end. Please try again later. If the problem persists, contact support. |
503 Service Unavailable | Server Error | A required downstream service (like our moderation service) is temporarily unavailable. |