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. This is more efficient and you'll get notified instantly when jobs complete.
https://api.beamgo.io
Authentication
All API requests require authentication using an API key. You can manage your API keys in your account dashboard.
Using Your API Key
Include your API key in the X-API-Key header of every request:
X-API-Key: your_api_key_here
Workflows
Workflows define the different AI tasks you can perform. Each workflow has a unique ID, specific parameters, and a credit cost.
Retrieves a list of all available workflows, their descriptions, and credit costs.
Example Request
curl "https://api.beamgo.io/workflows" \
-H "X-API-Key: your_api_key_here"import requests
url = "https://api.beamgo.io/workflows"
headers = {"X-API-Key": "your_api_key_here"}
response = requests.get(url, headers=headers)
print(response.json())Response Body
{
"workflows": [
{
"id": "text_to_video",
"description": "Generate a video from a text prompt",
"cost": 25
},
{
"id": "image_to_video",
"description": "Animate an image with optional text guidance",
"cost": 25
},
{
"id": "sound_to_video",
"description": "Generate lipsync video from audio and image",
"cost": 25
}
]
}
Text-to-Video
Generate a video from a text prompt.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Detailed description of the video content (max 1000 chars) |
aspect_ratio | string | No | One of: "1:1", "landscape (16:9)", "portrait (9:16)". Default: "landscape (16:9)" |
seed | integer | No | Seed for generation (0 = random). Default: 0 |
Example Request
curl -X POST "https://api.beamgo.io/workflows/text_to_video/run" \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A majestic dragon flying through a stormy sky",
"aspect_ratio": "landscape (16:9)",
"seed": 0
}'import requests
url = "https://api.beamgo.io/workflows/text_to_video/run"
headers = {"X-API-Key": "your_api_key_here"}
data = {
"prompt": "A majestic dragon flying through a stormy sky",
"aspect_ratio": "landscape (16:9)",
"seed": 0
}
response = requests.post(url, headers=headers, json=data)
print(response.json())// Using node-fetch: npm install node-fetch
import fetch from 'node-fetch';
const API_URL = "https://api.beamgo.io/workflows/text_to_video/run";
const API_KEY = "your_api_key_here";
const payload = {
prompt: "A majestic dragon flying through a stormy sky",
aspect_ratio: "landscape (16:9)",
seed: 0
};
const response = await fetch(API_URL, {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
const data = await response.json();
console.log(response.status, data);Response Body (202 Accepted)
{
"job_id": "123e4567-e89b-12d3-a456-426614174000",
"message": "Workflow job accepted."
}
Image-to-Video
Animate an image or extend a video with optional text guidance. Supports images (PNG, JPEG, WebP) and videos (MP4, WebM). Files must be sent as multipart/form-data.
You can now extend existing videos by providing either:
• A video file directly (max 20MB, 30s) - the last frame will be extracted and animated
• An
extend_from_job_id parameter to continue a previously generated video
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
input_file | file | Yes* | Image file (PNG, JPEG, WebP, max 2MB) OR Video file (MP4, WebM, max 20MB, 30s). *Required unless using extend_from_job_id |
prompt | string | No | Optional text prompt to guide the animation (max 1000 chars) |
seed | integer | No | Seed for generation (0 = random). Default: 0 |
extend_from_job_id | string (UUID) | No | Job ID of a previously generated video to extend. When provided, the last frame of that video will be used as the starting point. |
Example Request
# Example 1: Animate an image
curl -X POST "https://api.beamgo.io/workflows/image_to_video/run" \
-H "X-API-Key: your_api_key_here" \
-F "input_file=@/path/to/image.jpg" \
-F "prompt=make the image snow lightly" \
-F "seed=54321"
# Example 2: Extend an existing video
curl -X POST "https://api.beamgo.io/workflows/image_to_video/run" \
-H "X-API-Key: your_api_key_here" \
-F "extend_from_job_id=123e4567-e89b-12d3-a456-426614174000" \
-F "prompt=continue the scene with more movement"
# Example 3: Upload a video directly
curl -X POST "https://api.beamgo.io/workflows/image_to_video/run" \
-H "X-API-Key: your_api_key_here" \
-F "input_file=@/path/to/video.mp4" \
-F "prompt=extend this video smoothly"import requests
url = "https://api.beamgo.io/workflows/image_to_video/run"
headers = {"X-API-Key": "your_api_key_here"}
# Example 1: Animate an image
with open("image.jpg", "rb") as f:
files = {"input_file": f}
data = {"prompt": "make the image snow lightly", "seed": 54321}
response = requests.post(url, headers=headers, files=files, data=data)
print(response.json())
# Example 2: Extend a video
data = {
"extend_from_job_id": "123e4567-e89b-12d3-a456-426614174000",
"prompt": "continue the scene"
}
response = requests.post(url, headers=headers, data=data)
print(response.json())
# Example 3: Upload video file
with open("video.mp4", "rb") as f:
files = {"input_file": f}
data = {"prompt": "extend this video"}
response = requests.post(url, headers=headers, files=files, data=data)
print(response.json())// Using 'form-data': npm install form-data node-fetch
import FormData from 'form-data';
import fs from 'fs';
import fetch from 'node-fetch';
const API_URL = "https://api.beamgo.io/workflows/image_to_video/run";
const API_KEY = "your_api_key_here";
// Example 1: Animate an image
const form1 = new FormData();
form1.append('input_file', fs.createReadStream('./image.jpg'));
form1.append('prompt', "make the image snow lightly");
form1.append('seed', 54321);
let response = await fetch(API_URL, {
method: 'POST',
headers: { 'X-API-Key': API_KEY },
body: form1
});
console.log(await response.json());
// Example 2: Extend a video
const form2 = new FormData();
form2.append('extend_from_job_id', '123e4567-e89b-12d3-a456-426614174000');
form2.append('prompt', 'continue the scene');
response = await fetch(API_URL, {
method: 'POST',
headers: { 'X-API-Key': API_KEY },
body: form2
});
console.log(await response.json());Response Body (202 Accepted)
{
"job_id": "123e4567-e89b-12d3-a456-426614174000",
"message": "Workflow job accepted."
}
Sound-to-Video
Generate a lipsync video by combining an audio file with a static image. The AI will animate the image to match the audio.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
input_audio | file | Yes | Audio file (WAV or MP3, max 1MB) |
input_image | file | Yes | Image file (PNG, JPEG, WebP, max 2MB) |
prompt | string | No | Optional text prompt to guide the animation (max 1000 chars) |
duration | string | No | Video duration: "0:05" or "0:10" (paid plans only). Default: "0:05" |
seed | integer | No | Seed for generation (0 = random). Default: 0 |
Example Request
curl -X POST "https://api.beamgo.io/workflows/sound_to_video/run" -H "X-API-Key: your_api_key_here" -F "input_audio=@/path/to/speech.mp3" -F "input_image=@/path/to/portrait.jpg" -F "prompt=natural speaking animation" -F "duration=0:05" -F "seed=12345"import requests
url = "https://api.beamgo.io/workflows/sound_to_video/run"
headers = {"X-API-Key": "your_api_key_here"}
with open("speech.mp3", "rb") as audio, open("portrait.jpg", "rb") as image:
files = {
"input_audio": audio,
"input_image": image
}
data = {
"prompt": "natural speaking animation",
"duration": "0:05",
"seed": 12345
}
response = requests.post(url, headers=headers, files=files, data=data)
print(response.json())// Using 'form-data': npm install form-data node-fetch
import FormData from 'form-data';
import fs from 'fs';
import fetch from 'node-fetch';
const API_URL = "https://api.beamgo.io/workflows/sound_to_video/run";
const API_KEY = "your_api_key_here";
const form = new FormData();
form.append('input_audio', fs.createReadStream('./speech.mp3'));
form.append('input_image', fs.createReadStream('./portrait.jpg'));
form.append('prompt', 'natural speaking animation');
form.append('duration', '0:05');
form.append('seed', 12345);
const response = await fetch(API_URL, {
method: 'POST',
headers: {
'X-API-Key': API_KEY
// Content-Type is set automatically by form-data
},
body: form
});
const data = await response.json();
console.log(response.status, data);Response Body (202 Accepted)
{
"job_id": "123e4567-e89b-12d3-a456-426614174000",
"message": "Workflow job accepted."
}
Jobs
After submitting a workflow, you receive a job_id. Use this ID to track the job's progress and retrieve results when complete.
Retrieves the current status and details of a specific job. Returns a pre-signed URL for completed results.
Example Request
curl "https://api.beamgo.io/jobs/123e4567-e89b-12d3-a456-426614174000/status" -H "X-API-Key: your_api_key_here"import requests
job_id = "123e4567-e89b-12d3-a456-426614174000"
url = f"https://api.beamgo.io/jobs/{job_id}/status"
headers = {"X-API-Key": "your_api_key_here"}
response = requests.get(url, headers=headers)
print(response.json())// Using node-fetch: npm install node-fetch
import fetch from 'node-fetch';
const JOB_ID = "123e4567-e89b-12d3-a456-426614174000";
const API_URL = `https://api.beamgo.io/jobs/${JOB_ID}/status`;
const API_KEY = "your_api_key_here";
const response = await fetch(API_URL, {
method: 'GET',
headers: { 'X-API-Key': API_KEY }
});
const data = await response.json();
console.log(response.status, data);Response Body
The response varies based on job status:
Status: PENDING or PROCESSING
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"status": "PROCESSING",
"progress": 45,
"created_at": "2024-05-20T12:00:00Z",
"updated_at": "2024-05-20T12:01:30Z"
}
Status: COMPLETED
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"status": "COMPLETED",
"progress": 100,
"result_video_url": "https://storage.example.com/video.mp4?signature=...",
"thumbnail_url": "https://storage.example.com/thumbnail.jpg?signature=...",
"created_at": "2024-05-20T12:00:00Z",
"updated_at": "2024-05-20T12:02:45Z"
}
Status: FAILED
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"status": "FAILED",
"error_message": "Content moderation check failed",
"created_at": "2024-05-20T12:00:00Z",
"updated_at": "2024-05-20T12:00:15Z"
}
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.beamgo.io/jobs/123e4567-e89b-12d3-a456-426614174000/download" -H "X-API-Key: your_api_key_here"import requests
API_KEY = "your_api_key_here"
JOB_ID = "123e4567-e89b-12d3-a456-426614174000"
API_URL = f"https://api.beamgo.io/jobs/{JOB_ID}/download"
response = requests.get(API_URL, headers={"X-API-Key": API_KEY})
print(response.json())// Using node-fetch: npm install node-fetch
import fetch from 'node-fetch';
const JOB_ID = "123e4567-e89b-12d3-a456-426614174000";
const API_URL = `https://api.beamgo.io/jobs/${JOB_ID}/download`;
const API_KEY = "your_api_key_here";
const response = await fetch(API_URL, {
method: 'GET',
headers: { 'X-API-Key': API_KEY }
});
const data = await response.json();
console.log(response.status, data);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.beamgo.io/jobs?limit=10&offset=10" -H "X-API-Key: your_api_key_here"import requests
API_KEY = "your_api_key_here"
API_URL = "https://api.beamgo.io/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())// Using node-fetch: npm install node-fetch
import fetch from 'node-fetch';
const API_URL = "https://api.beamgo.io/jobs";
const API_KEY = "your_api_key_here";
const params = new URLSearchParams({
limit: '10',
offset: '10'
});
const response = await fetch(`${API_URL}?${params}`, {
method: 'GET',
headers: { 'X-API-Key': API_KEY }
});
const totalCount = response.headers.get('x-total-count');
const data = await response.json();
console.log(`Total jobs: ${totalCount}`);
console.log(response.status, data);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.beamgo.io/jobs/123e4567-e89b-12d3-a456-426614174000" -H "X-API-Key: your_api_key_here"import requests
API_KEY = "your_api_key_here"
JOB_ID = "123e4567-e89b-12d3-a456-426614174000"
API_URL = f"https://api.beamgo.io/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}")// Using node-fetch: npm install node-fetch
import fetch from 'node-fetch';
const JOB_ID = "123e4567-e89b-12d3-a456-426614174000";
const API_URL = `https://api.beamgo.io/jobs/${JOB_ID}`;
const API_KEY = "your_api_key_here";
const response = await fetch(API_URL, {
method: 'DELETE',
headers: { 'X-API-Key': API_KEY }
});
if (response.status === 204) {
console.log("Job deleted successfully.");
} else {
const errorData = await response.text();
console.log(`Error: ${response.status} - ${errorData}`);
}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.
Your webhook secret_token is automatically generated and returned ONLY ONCE when you create the webhook.
- You MUST save this token immediately - there is no way to retrieve it later
- If you lose the token, you must DELETE and RECREATE the webhook to get a new one
- The secret token is used to verify webhook signatures and ensure notifications genuinely come from BeamGo
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. The secret_token is ONLY returned in this response.
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.beamgo.io/webhooks" -H "X-API-Key: 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.beamgo.io/webhooks",
headers={"X-API-Key": "your_api_key_here"},
json=payload
)
result = response.json()
# SAVE THIS TOKEN IMMEDIATELY!
secret_token = result.get("secret_token")
print(f"Secret Token (save this!): {secret_token}")// Using node-fetch: npm install node-fetch
import fetch from 'node-fetch';
const API_URL = "https://api.beamgo.io/webhooks";
const API_KEY = "your_api_key_here";
const payload = {
url: "https://myapp.com/api/ai-video-webhook",
events: ["job.completed", "job.failed"],
description: "Production notifications"
};
const response = await fetch(API_URL, {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
const data = await response.json();
// SAVE THIS TOKEN IMMEDIATELY!
const secretToken = data.secret_token;
console.log(`Secret Token (save this!): ${secretToken}`);
console.log(response.status, data);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.beamgo.io/webhooks" -H "X-API-Key: your_api_key_here"import requests
response = requests.get("https://api.beamgo.io/webhooks", headers={"X-API-Key": "your_api_key_here"})
print(response.json())// Using node-fetch: npm install node-fetch
import fetch from 'node-fetch';
const API_URL = "https://api.beamgo.io/webhooks";
const API_KEY = "your_api_key_here";
const response = await fetch(API_URL, {
method: 'GET',
headers: { 'X-API-Key': API_KEY }
});
const data = await response.json();
console.log(response.status, data);Delete Webhook
Deletes the webhook configuration with the specified ID.
Example Request
curl -X DELETE "https://api.beamgo.io/webhooks/e4a7a2a7-12d4-4f4c-83de-724f33a8b4a5" -H "X-API-Key: your_api_key_here"import requests
WEBHOOK_ID = "e4a7a2a7-12d4-4f4c-83de-724f33a8b4a5"
response = requests.delete(
f"https://api.beamgo.io/webhooks/{WEBHOOK_ID}",
headers={"X-API-Key": "your_api_key_here"}
)
print(f"Status Code: {response.status_code}") # Expect 204 for success// Using node-fetch: npm install node-fetch
import fetch from 'node-fetch';
const WEBHOOK_ID = "e4a7a2a7-12d4-4f4c-83de-724f33a8b4a5";
const API_URL = `https://api.beamgo.io/webhooks/${WEBHOOK_ID}`;
const API_KEY = "your_api_key_here";
const response = await fetch(API_URL, {
method: 'DELETE',
headers: { 'X-API-Key': API_KEY }
});
console.log(`Status Code: ${response.status}`); // 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.beamgo.io/webhooks/e4a7a2a7-12d4-4f4c-83de-724f33a8b4a5/test" -H "X-API-Key: your_api_key_here"import requests
WEBHOOK_ID = "e4a7a2a7-12d4-4f4c-83de-724f33a8b4a5"
response = requests.post(
f"https://api.beamgo.io/webhooks/{WEBHOOK_ID}/test",
headers={"X-API-Key": "your_api_key_here"}
)
print(response.status_code, response.json())// Using node-fetch: npm install node-fetch
import fetch from 'node-fetch';
const WEBHOOK_ID = "e4a7a2a7-12d4-4f4c-83de-724f33a8b4a5";
const API_URL = `https://api.beamgo.io/webhooks/${WEBHOOK_ID}/test`;
const API_KEY = "your_api_key_here";
const response = await fetch(API_URL, {
method: 'POST',
headers: { 'X-API-Key': API_KEY }
});
const data = await response.json();
console.log(response.status, data);Example Response
{
"message": "Test webhook dispatch initiated. Check your endpoint for the payload.",
"test_payload": {
"job_id": "...", "status": "COMPLETED", ...
}
}
Account
Manage your account, check credit balance, and view usage.
Retrieves your user profile and credit information.
Example Request
curl "https://api.beamgo.io/users/me/profile" -H "X-API-Key: your_api_key_here"import requests
url = "https://api.beamgo.io/users/me/profile"
headers = {"X-API-Key": "your_api_key_here"}
response = requests.get(url, headers=headers)
print(response.json())// Using node-fetch: npm install node-fetch
import fetch from 'node-fetch';
const API_URL = "https://api.beamgo.io/users/me/profile";
const API_KEY = "your_api_key_here";
const response = await fetch(API_URL, {
method: 'GET',
headers: { 'X-API-Key': API_KEY }
});
const data = await response.json();
console.log(response.status, data);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": 3500,
"monthly_credits_balance": 3200,
"purchased_credits_balance": 500,
"reserved_credits": 50,
"current_period_end": "2024-06-20T12:00:00Z",
"next_plan_id": null,
"available_credits": 3650
}
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.
Job Creation Limits
Concurrent Jobs
This is the number of jobs you can have in PENDING or PROCESSING status at the same time.
| Plan | Concurrent Jobs |
|---|---|
| Free | 1 |
| Basic | 2 |
| Pro | 6 |
| Enterprise | 20 |
Temporal Limits
These limits control the number of jobs you can create over a period of time.
| Plan | Hourly Limit | Daily Limit |
|---|---|---|
| Free | 2 | 2 |
| Basic | 5 | 10 |
| Pro | 10 | 20 |
| Enterprise | 100 | 100 |
Polling Best Practices
If you choose to poll the GET /jobs/{id}/status endpoint to check job status, please follow these best practices:
Polling Rate Limits
To prevent server overload, we enforce the following limits on status polling:
| Plan | Requests per Minute | Requests per Hour |
|---|---|---|
| All Plans | 60 (1 req/sec) | 3600 |
⚠️ Polling Guidelines
- Recommended interval: Poll every 5-10 seconds for active jobs
- DO NOT poll faster than 1 request per second - this provides no benefit as videos take time to generate
- Stop polling immediately once the job reaches a terminal state (
COMPLETED,FAILED, orCANCELLED) - Use webhooks instead: Webhooks are more efficient, you'll get notified instantly, and you won't need to poll at all
Example: Polling with Proper Rate Limiting
import requests
import time
job_id = "123e4567-e89b-12d3-a456-426614174000"
url = f"https://api.beamgo.io/jobs/{job_id}/status"
headers = {"X-API-Key": "your_api_key_here"}
while True:
response = requests.get(url, headers=headers)
if response.status_code == 429:
# Rate limited - wait before retrying
retry_after = int(response.headers.get('Retry-After', 60))
print(f"Rate limited. Waiting {retry_after} seconds...")
time.sleep(retry_after)
continue
data = response.json()
status = data.get('status')
print(f"Job status: {status}")
# Stop polling if job is complete
if status in ['COMPLETED', 'FAILED', 'CANCELLED']:
break
# Wait 5 seconds before next check (well within limits)
time.sleep(5)
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. |
429 Too Many Requests | Client Error | You have exceeded a rate limit (concurrent jobs, temporal limits, or polling limits). |
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. |