General Information
Bach Video Generation API TEST
Overview
The Bach Video Generation API enables developers to programmatically generate high-quality videos from text prompts, static images, or multi-image compositions. Built on state-of-the-art generative AI models, the API provides a comprehensive suite of endpoints for creative video production at scale.
Base URL
https://api-gen-na.bach.art/api/vdr
Content-Type: application/json
Authentication
The Bach API uses JWT (JSON Web Token) authentication based on the HMAC-SHA256 signing algorithm, compliant with RFC 7519.
Step 1: Obtain Credentials
Log in to the Bach Developer Console to retrieve your AccessKey and SecretKey.
Step 2: Generate an API Token
Construct a JWT token using the following code. The token consists of three parts: Header, Payload, and Signature.
import jwt
from datetime import datetime, timedelta
ak = "" # Your Access Key
sk = "" # Your Secret Key
def generate_token(ak: str, sk: str) -> str:
now = datetime.now()
headers = {
'alg': 'HS256', # Signing algorithm: HMAC-SHA256
'typ': 'JWT' # Token type
}
payload = {
'iss': ak, # Issuer
'nbf': int((now - timedelta(seconds=5)).timestamp()), # Not valid before (5s grace)
'exp': int((now + timedelta(days=10)).timestamp()) # Expires in 10 days
}
secret_key = sk.encode('utf-8')
token = jwt.encode(payload, secret_key, headers=headers)
return token
api_token = generate_token(ak, sk)
print(api_token)
Step 3: Attach the Authorization Header
Include the generated token in the Authorization header of every request:
Authorization: Bearer <YOUR_API_TOKEN>
Note: Ensure there is exactly one space between
Bearerand the token string.
Enumeration Reference
Model Name (model_name)
| Endpoint Type | Allowed Values | Description |
|---|---|---|
| Text-to-Video | bach-1.0-preview | Default video generation model |
| Image-to-Video | bach-1.0-preview | Default video generation model |
| Multi-Image-to-Video | bach-1.0-preview | Default video generation model |
Resolution (resolution)
| Value | Description |
|---|---|
720p | Standard definition (case-sensitive) |
1080p | High definition (case-sensitive) |
Duration (duration)
| Endpoint Type | Allowed Values | Description |
|---|---|---|
| Text-to-Video | 6 | Fixed at 6 seconds |
| Image-to-Video | 1, 2, 3, 4, 5 | 1–5 seconds |
| Multi-Image-to-Video | 1, 2, 3, 4, 5 | 1–5 seconds |
Frame Rate (fps)
| Value | Description |
|---|---|
24 | 24 frames per second (currently the only supported value) |
Task Status (status)
| Status | Description |
|---|---|
TASK_PENDING | Task has been submitted and is queued for processing |
TASK_PROCESSING | Task is actively being processed |
TASK_SUCCEEDED | Generation completed successfully |
TASK_FAILED | Generation failed; refer to the message field for details |
Response Codes
All API responses include an HTTP status code and a business-level code in the JSON body.
| HTTP Status | Business Code | Description | Recommended Action |
|---|---|---|---|
| 200 | 200 | Success | Request completed successfully |
| 400 | 1000 | Invalid parameter | Check the message field for specific parameter errors. See Parameter Error Details |
| 400 | 1001 | Sensitive content detected | Modify or remove the flagged content |
| 401 | 1100 | Authentication failed | Verify that the Authorization header is correct |
| 401 | 1101 | Authorization header missing | Include a valid Authorization header |
| 401 | 1102 | Token not yet valid | Wait for the token's nbf time, or regenerate |
| 401 | 1103 | Token expired | Generate a new token |
| 404 | 1200 | Resource not found | The requested task or resource does not exist |
| 404 | 1203 | Batch ID not found or expired | Provide a valid, non-expired batch ID |
| 403 | 1300 | Duration not supported by plan | Upgrade your credit package to access this duration |
| 403 | 1301 | Resolution not supported by plan | Upgrade your credit package to access this resolution |
| 403 | 1302 | Insufficient credits | Top up your credit package |
| 429 | 1800 | Rate limit exceeded | Reduce request frequency or contact support for a quota increase |
| 500 | 5000 | Internal server error | Retry the request; contact support if the issue persists |
Parameter Error Details
When the API returns HTTP 400 with business code 1000, the message field describes the specific validation failure. The table below lists all possible parameter error messages, their causes, and recommended resolutions.
General Parameters
| Error Message | Cause | Resolution |
|---|---|---|
Model name is required. | Missing or empty model_name | Provide a valid model name (e.g., bach-1.0-preview) |
Prompt is required. | Missing prompt field | Provide a non-empty text prompt |
Duration must be between 1 and 5 seconds. | Invalid duration for Image-to-Video / Multi-Image-to-Video | Use an integer between 1 and 5 |
Duration must be 6 seconds. | Invalid duration for Text-to-Video | Use 6 |
Resolution must be 720p or 1080p. | Invalid resolution value | Use 720p or 1080p (case-sensitive) |
Aspect ratio must be 16:9, 9:16, or 1:1. | Invalid aspect_ratio value | Use 16:9, 9:16, or 1:1 |
Seed must be between 0 and 10000000. | Seed value out of range | Use an integer between 0 and 10,000,000 |
The prompt length must not exceed 10000 characters. | Prompt text too long | Shorten the prompt to 10,000 characters or fewer |
The negative prompt length must not exceed 10000 characters. | Negative prompt text too long | Shorten to 10,000 characters or fewer |
The audio prompt length must not exceed 200 characters. | Audio prompt text too long | Shorten to 200 characters or fewer |
The callback url length must not exceed 500 characters. | Callback URL too long | Shorten to 500 characters or fewer |
Task Id is required. | Missing task_id | Provide a valid task ID |
Image URL must be a valid HTTP or HTTPS URL | Malformed image URL | Ensure the URL starts with http:// or https:// |
Multi-Image-to-Video Parameters
| Error Message | Cause | Resolution |
|---|---|---|
Image URL is required. | Missing image_url field | Provide a valid image URL array |
Image URL cannot be empty. | Empty image_url array | Include at least one element |
Name is required. | Missing prompt field | Provide a text prompt |
Image URL list cannot exceed 9 elements. | Too many elements in image_url | Limit to 9 elements maximum |
Image URL list element at index {n} cannot be null. | Null element in array | Remove null entries |
Image URL at index {n} cannot be empty. | Empty string URL | Provide a valid URL string |
URL array at index {n} cannot be empty. | Empty nested URL array | Include at least one URL in nested arrays |
URL array at index {n} cannot exceed 4 URLs. | Too many URLs in a nested array | Limit each nested array to 4 URLs |
URL array at index {n} contains non-string element at position {m}. | Non-string value in URL array | Ensure all elements are strings |
URL in array at index {n}, position {m} cannot be empty. | Empty URL within nested array | Provide a valid URL |
Image URL list element at index {n} must be either a string URL or a URL array. | Invalid element type | Use either a string or an array of strings |
Subject name is required. | Missing subject_name | Provide a name (max 50 characters) |
The name length must not exceed 50 characters. | Subject name too long | Shorten to 50 characters or fewer |
The desc length must not exceed 500 characters. | Subject description too long | Shorten to 500 characters or fewer |
Subject type must be either 'character' or 'object' | Invalid subject_type | Use character or object |
Batch Upload Parameters
| Error Message | Cause | Resolution |
|---|---|---|
The upload image list cannot be empty. | No images provided | Include at least one image |
The upload type cannot be empty. | Missing upload_type | Specify url or base64 |
The upload type can only be url or base64. | Invalid upload type | Use url or base64 |
Batch upload supports a maximum of {n} images. | Too many images in batch | Limit to 300 images per batch |
The {n}th image: For file type, please use the submit-with-files interface. | Wrong endpoint for file upload | Use /batch-upload/submit-with-files |
The {n}th image: imageData cannot be empty. | Missing image data | Provide a valid URL or Base64 string |
The {n}th image URL does not have a valid file extension. | URL missing file extension | Append a supported format extension |
The {n}th image URL format '{ext}' is not supported. | Unsupported image format | Use: jpg, jpeg, png, gif, bmp, webp, svg, ico, tiff, tif |
The {n}th image (base64) size is approximately {size}MB, exceeds the maximum limit of 10MB. | Base64 image too large | Reduce file size to under 10 MB |
The {n}th image (base64): Cannot determine image format. | Format detection failed | Include a format parameter or use data URI format |
The {n}th image (base64) format '{format}' is not supported. | Unsupported Base64 format | Use a supported format |
The upload file list cannot be empty. | No files uploaded | Include at least one file |
The {n}th image '{filename}' size is {size}MB, exceeds the maximum limit of 10MB. | File too large | Reduce file size to under 10 MB |
The length of imageNames array must match the length of files array. | Name/file count mismatch | Ensure array lengths match |
The {n}th file '{filename}' is not an image. | Non-image file detected | Upload valid image files only |
The {n}th file '{filename}' extension '{ext}' is not supported. | Unsupported file extension | Use a supported image format |
The {n}th file '{filename}' does not have a valid file extension. | Missing file extension | Add a supported format extension |
Best Practices
Error Handling
Implement structured error handling to manage API responses gracefully:
import requests
def create_video_task(payload: dict, api_token: str) -> dict:
headers = {
"Authorization": f"Bearer {api_token}",
"Content-Type": "application/json"
}
response = requests.post(
"https://api-gen-na.bach.art/api/vdr/submit",
headers=headers,
json=payload
)
if response.status_code 200:
return response.json()
elif response.status_code 400:
error_data = response.json()
raise ValueError(f"Parameter error: {error_data.get('message')}")
elif response.status_code 401:
raise PermissionError("Authentication failed. Check your API token.")
elif response.status_code 429:
raise ResourceWarning("Rate limit exceeded. Please retry later.")
else:
raise Exception(f"Unexpected error: {response.status_code}")
Task Status Polling
capability_map_en.md
Video generation is asynchronous. After submitting a task, poll the corresponding query endpoint at regular intervals until the task reaches a terminal state (TASK_SUCCEEDED or TASK_FAILED).
import time
def wait_for_completion(task_id: str, api_token: str, max_attempts: int = 60) -> dict:
headers = {
"Authorization": f"Bearer {api_token}",
"Content-Type": "application/json"
}
for _ in range(max_attempts):
response = requests.get(
f"https://api-gen-na.bach.art/api/vdr/status/{task_id}",
headers=headers
)
result = response.json()
status = result.get("status")
if status "TASK_SUCCEEDED":
return result
elif status "TASK_FAILED":
raise Exception("Video generation failed")
time.sleep(10) # Poll every 10 seconds
raise TimeoutError("Task did not complete within expected time")
Tip: We recommend a polling interval of 10 seconds for video generation tasks and 2 seconds for batch upload tasks.
Rate Limits
The API enforces rate limits to ensure service stability. If you exceed your allocated quota, the API returns HTTP 429. Implement exponential backoff in your retry logic to handle rate-limited requests gracefully.
Last updated: March 2026