Unified Media Studio API for n8n
This reference describes every business API endpoint exposed by the unified Space and how to call it with n8n's HTTP Request node.
Base URL
Store the deployed Space URL in an n8n variable:
STUDIO_BASE_URL=https://<space-subdomain>.hf.space
Use this expression in HTTP Request nodes:
{{ $vars.STUDIO_BASE_URL }}/health
Do not add a trailing slash to STUDIO_BASE_URL.
Standard HTTP Request Node Settings
JSON request
- Method: Use the method in the endpoint tables.
- URL:
{{ $vars.STUDIO_BASE_URL }}<path> - Send Body: On
- Body Content Type: JSON
- Specify Body: Using JSON
- Response Format: JSON
For routes marked API key, add a Header Auth credential or enable Send Headers:
X-API-Key: <AVA2LON_API_KEY value>
The header is only enforced when AVA2LON_API_KEY or BASYX_API_KEY is set in
the Space environment.
Query parameters
- Enable Send Query Parameters.
- Add each query parameter shown in the endpoint table.
- Do not place simple query parameters in the JSON body.
Multipart file upload
- Send Body: On
- Body Content Type: Form-Data
- For text fields, select Parameter Type: Form Data.
- For files, select Parameter Type: n8n Binary File.
- Set Name to the API field name, usually
fileorfiles. - Set Input Data Field Name to the incoming n8n binary field, commonly
data.
Add another files parameter for every additional binary file.
File download response
For endpoints marked File response:
- Set Response Format to File.
- Set Put Output in Field to
data. - The following n8n node can read the output from
$binary.data.
Asynchronous job workflow
Most renderer operations return:
{
"job_id": "job_123",
"status_url": "/status/job_123",
"download_url": "/download/job_123?token=..."
}
Recommended n8n flow:
- HTTP Request submits the job.
- Wait node pauses for several seconds.
- HTTP Request calls
{{ $vars.STUDIO_BASE_URL }}{{ $json.status_url }}. - IF node checks whether
stateequalsCOMPLETED,FAILED, orCANCELLED. - Loop through Wait while the state is
PENDINGorRUNNING. - Download using the original submission node's
download_url.
For payloads with callback_url, use an n8n Webhook node's production URL to
avoid polling.
Render callbacks use render.completed, render.failed, and
render.cancelled; toolkit and analysis callbacks use task.*. The event is
available in both the JSON event property and X-Ava2lon-Event header.
Root and Discovery
| Method | Path | n8n input | Response |
|---|---|---|---|
| GET | / |
None | Redirects to /dashboard; use only for browser access. |
| GET | /apps |
None | JSON map of mounted applications and MCP tool count. |
Renderer Discovery and Monitoring
These routes use the root base URL.
| Method | Path | n8n input | Response |
|---|---|---|---|
| GET | /health |
None | Renderer health. |
| GET | /healthz |
None | Health-check alias for hosting probes. |
| GET | /monitor |
None | Runtime, queue, storage, and capability summary. |
| GET | /queue |
None | Job queue summary. |
| GET | /workers |
None | Worker and runtime settings. |
| GET | /presets |
None | Presets, templates, styles, transitions, and task IDs. |
| GET | /platforms |
None | Platform profile metadata. |
| GET | /toolkit/tasks |
None | Renderer toolkit task names. |
| GET | /capabilities |
None | Complete capability catalog. |
| GET | /effects |
None | Effects catalog. |
| GET | /filters |
None | Filter catalog. |
| GET | /transitions |
None | Transition catalog. |
| GET | /templates/catalog |
None | Templates, presets, and styles. |
| GET | /projects |
None | List saved projects. |
Projects and Timeline
| Method | Path | n8n input | Auth | Response |
|---|---|---|---|---|
| POST | /projects |
JSON ProjectPayload |
API key | Created project. |
| POST | /project/create |
JSON ProjectPayload |
API key | Alias of /projects. |
| GET | /project/{project_id} |
Replace {project_id} |
None | Project JSON. |
| POST | /project/save |
JSON ProjectSavePayload |
API key | Saved project. |
| POST | /project/assets/add |
JSON ProjectAssetPayload |
API key | Updated project. |
| POST | /timeline/add |
JSON TimelineAddPayload |
API key | Updated project. |
| POST | /timeline/operation |
JSON TimelineOperationPayload |
API key | Updated project. |
| POST | /timeline/split |
JSON TimelineOperationPayload |
API key | Runs split. |
| POST | /timeline/trim |
JSON TimelineOperationPayload |
API key | Runs trim. |
| POST | /timeline/ripple-delete |
JSON TimelineOperationPayload |
API key | Runs ripple_delete. |
| POST | /timeline/insert |
JSON TimelineOperationPayload |
API key | Runs insert. |
| POST | /timeline/replace |
JSON TimelineOperationPayload |
API key | Runs replace. |
| POST | /timeline/group |
JSON TimelineOperationPayload |
API key | Runs group. |
| POST | /timeline/lock |
JSON TimelineOperationPayload |
API key | Runs lock. |
| POST | /timeline/hide |
JSON TimelineOperationPayload |
API key | Runs hide. |
| POST | /timeline/duplicate |
JSON TimelineOperationPayload |
API key | Runs duplicate. |
| POST | /effect/apply |
JSON EffectApplyPayload |
API key | Updated project or asynchronous job. |
| POST | /filter/apply |
JSON FilterApplyPayload |
API key | Updated project or asynchronous job. |
| POST | /transition/add |
JSON TransitionAddPayload |
API key | Updated project or asynchronous job. |
| POST | /keyframe/add |
JSON KeyframePayload |
API key | Updated project. |
Example project creation:
{
"name": "Campaign 01",
"metadata": {
"platform": "tiktok",
"creative_style": "high_energy"
},
"export_settings": {
"platform": "tiktok"
}
}
AI and Generation
All routes in this table return asynchronous job information.
| Method | Path | n8n input | Auth |
|---|---|---|---|
| POST | /caption/generate |
JSON CaptionGeneratePayload |
API key |
| POST | /music/generate |
JSON GenerationPayload |
API key |
| POST | /voice/generate |
JSON GenerationPayload |
API key |
| POST | /image/generate |
JSON GenerationPayload |
API key |
| POST | /video/generate |
JSON GenerationPayload |
API key |
| POST | /ai/{tool} |
Replace {tool}; JSON AIToolPayload |
API key |
| POST | /assistant/{tool} |
Replace {tool}; JSON AIToolPayload |
API key |
Example:
{
"prompt": "Upbeat cinematic background music",
"provider": "local",
"callback_url": "https://n8n.example/webhook/studio-complete",
"params": {
"duration": 20
}
}
Rendering and Uploads
| Method | Path | n8n input | Auth | Response |
|---|---|---|---|---|
| POST | /render |
JSON RenderPayload or AIReelsPayload |
None | Async job. |
| POST | /render/variants |
JSON RenderVariantsPayload |
None | Render group plus child jobs. |
| POST | /render/template |
JSON TemplateRenderPayload |
None | Async job. |
| POST | /render/ai-reels |
JSON AIReelsPayload |
None | Async job. |
| POST | /render/batch |
JSON BatchPayload |
None | Array of job IDs. |
| POST | /automation/batch |
JSON BatchPayload |
API key | Array of job IDs. |
| POST | /project/{project_id}/render |
Replace {project_id}; JSON ProjectRenderPayload |
API key | Async job. |
| POST | /render/upload |
Multipart request_json plus zero or more files |
None | Async job. |
| POST | /render/ai-reels/upload |
Multipart request_json plus zero or more files |
None | Async job. |
| POST | /assets/upload |
Multipart; one or more files |
None | Uploaded asset references. |
| POST | /upload |
Multipart files; optional expand_zip |
None | Uploaded or expanded assets. |
| GET | /render/groups/{group_id} |
Replace {group_id} |
None | Aggregate state and child jobs. |
| GET | /templates/automation |
None | None | Data-driven render templates. |
Basic render body:
{
"scenes": [
{
"start": 0,
"duration": 5,
"media": "https://example.com/video.mp4",
"caption": "Opening hook",
"transition": "fade",
"background": "blur",
"layout": "fill"
}
],
"output_name": "campaign.mp4",
"template": "tiktok_classic",
"auto_subtitles": true,
"subtitle_language": "en"
}
For /render/upload, configure n8n Form-Data as:
| Parameter Type | Name | Value |
|---|---|---|
| Form Data | request_json |
JSON string shown below |
| n8n Binary File | files |
Input Data Field Name such as data |
{
"scenes": [
{
"start": 0,
"duration": 5,
"media": "upload://clip.mp4",
"caption": "Uploaded clip"
}
],
"output_name": "render.mp4"
}
The filename in upload://clip.mp4 must match the uploaded binary filename.
Render several platform outputs from one timeline with /render/variants:
{
"scenes": [{"start": 0, "duration": 12, "media": "https://example.com/input.mp4"}],
"callback_url": "https://n8n.example/webhook/render-events",
"variants": [
{"name": "shorts", "platform": "youtube_shorts", "output_name": "shorts.mp4"},
{"name": "reels", "platform": "instagram_reels", "output_name": "reels.mp4"},
{"name": "youtube", "platform": "youtube_1080p", "output_name": "youtube.mp4"}
]
}
Use /render/template for spreadsheet, CRM, and database-driven renders. An
exact placeholder preserves arrays, objects, numbers, and booleans instead of
converting them to strings.
{
"template": "vertical-captioned-clip",
"variables": {
"output_name": "customer-42.mp4",
"scenes": [{"start": 0, "duration": 8, "media": "https://example.com/42.mp4"}],
"voiceover": null,
"background_music": null
}
}
Platform Processing and Toolkit
All routes in this table require X-API-Key and return asynchronous job
information.
| Method | Path | n8n input |
|---|---|---|
| POST | /ingest |
JSON IngestPayload |
| POST | /analyze |
JSON AnalyzePayload |
| POST | /clips |
JSON ClipsPayload |
| POST | /thumbnail |
JSON ThumbnailPayload |
| POST | /thumbnail/create |
JSON ThumbnailPayload |
| POST | /metadata |
JSON MetadataPayload |
| POST | /publish |
JSON PublishPayload |
| POST | /toolkit |
JSON ToolkitPayload |
| POST | /edit |
JSON ToolkitPayload; alias of /toolkit |
Toolkit example:
{
"task": "compress",
"media": "https://example.com/input.mp4",
"output_name": "compressed.mp4",
"params": {
"crf": 28,
"resolution": "720p"
}
}
FFmpeg automation tasks added for n8n:
| Task | Important params |
Download artifact |
|---|---|---|
inspect |
None | FFprobe metadata JSON |
loudness_analyze |
target_lufs |
LUFS/LRA/true-peak JSON |
silence_detect |
noise_db, duration_seconds |
Timed silence events JSON |
black_detect |
pixel_threshold, duration_seconds |
Timed black-frame events JSON |
scene_detect |
threshold |
Scene-change timestamps JSON |
contact_sheet |
columns, rows, interval_seconds, thumbnail_width |
JPEG/PNG |
hls |
segment_seconds, playlist_type, crf |
ZIP with M3U8 and TS segments |
All use the normal POST /toolkit body with task, media, optional params,
and optional callback_url.
Transcription, Subtitles, Jobs, and Downloads
| Method | Path | n8n input | Response |
|---|---|---|---|
| POST | /transcribe |
JSON TranscribePayload |
Transcription JSON. |
| POST | /subtitles |
JSON SubtitlePayload |
File response (.srt or .ass). |
| POST | /scene-builder |
JSON SceneBuildPayload |
Generated scene array. |
| POST | /transcribe/upload |
Multipart file plus optional transcription fields |
Transcription JSON. |
| GET | /status |
Optional query job_id |
Service status without job_id; job record with it. |
| GET | /status/{job_id} |
Replace {job_id} |
Job record. |
| POST | /cancel/{job_id} |
Replace {job_id} |
Updated job record. |
| POST | /admin/cleanup |
Optional query older_than_seconds |
Cleanup counts. |
| GET | /download |
Query job_id; optional token |
File response. |
| GET | /download/{job_id} |
Replace {job_id}; optional query token |
File response. |
| POST | /inspect |
Query path |
Media metadata JSON. |
| POST | /media/inspect |
JSON { "media": "...", "callback_url": "..." } |
Async remote-safe inspection. |
Transcription body:
{
"audio": "https://example.com/audio.mp3",
"model_size": "tiny",
"language": "en",
"task": "transcribe",
"beam_size": 5,
"vad_filter": true,
"word_timestamps": true
}
Subtitle body:
{
"events": [
{
"start": 0,
"end": 2.5,
"text": "Opening caption"
}
],
"format": "srt",
"template": "tiktok_classic"
}
Kokoro TTS
| Method | Path | n8n input | Response |
|---|---|---|---|
| POST | /tts/v1/audio/speech |
JSON shown below | WAV file response. |
Set the HTTP Request node's response format to File.
{
"input": "This is generated speech.",
"voice": "af_bella.pt",
"model": "kokoro-v0_19.onnx",
"speed": 1.0
}
voice and model are optional; the server uses its first configured voice and
model when omitted.
MusicGen
| Method | Path | n8n input | Response |
|---|---|---|---|
| GET | /music/health |
None | Health JSON. |
| POST | /music/generate |
Query prompt; optional query duration |
WAV file response. |
For generation:
- Method: POST
- URL:
{{ $vars.STUDIO_BASE_URL }}/music/generate - Send Query Parameters: On
prompt:Soft cinematic instrumentalduration:10- Response Format: File
Whisper Operator
| Method | Path | n8n input | Response |
|---|---|---|---|
| POST | /whisper/execute/{task_name} |
Multipart file or URL fields | JSON or file response. |
| GET | /whisper/api/health |
None | Health JSON. |
| GET | /whisper/api/status/{job_id} |
Replace {job_id} |
Whisper queue status. |
Use one of these multipart inputs for /whisper/execute/{task_name}:
file: n8n Binary File.url_input: downloadable media URL.source: alternative media URL.webhook: optional callback URL.
Supported task names:
autonomous
auto-publish
publish
bulk-publish
generate-metadata
generate-thumbnail
schedule-post
transcribe
subtitles
render
highlights
clips
viral-score
strategy
batch
FFmpeg Editor
| Method | Path | n8n input | Response |
|---|---|---|---|
| GET | /editor/healthz |
None | Health and dependency checks. |
| GET | /editor/readyz |
None | Readiness; returns 503 when dependencies fail. |
| GET | /editor/tasks |
None | Editor task registry. |
| POST | /editor/n8n/execute/{task_id} |
JSON, multipart, or raw binary | Synchronous file response. |
| POST | /editor/n8n/jobs/{task_id} |
JSON, multipart, or raw binary | Background job JSON. |
| POST | /editor/execute/{task_id} |
Multipart fields | Synchronous file response. |
| POST | /editor/jobs/{task_id} |
Multipart fields | Background job JSON. |
| GET | /editor/status/{job_id} |
Replace {job_id} |
Background job status. |
| GET | /editor/download/{job_id} |
Replace {job_id} |
File response. |
| GET | /editor/history |
None | Recent output metadata. |
| GET | /editor/history/{history_id}/download |
Replace {history_id} |
File response. |
Recommended editor request for n8n
Use /editor/n8n/jobs/{task_id} for long-running jobs.
Multipart request:
- Add one or more n8n Binary File parameters. The field name may be
files. - Add text options as Form Data.
- A URL may use
url,urls,file_url,source_url, ordownload_url.
JSON request:
{
"url": "https://example.com/input.mp4",
"options": {
"resolution": "720p",
"crf": "28",
"preset": "medium",
"text": "Caption text"
}
}
Raw binary request:
- Body Content Type: n8n Binary File
- Input Data Field Name:
data - Add header
X-Filename: input.mp4 - Put editor options in query parameters.
Available editor option fields:
text
start_time
end_time
duration
aspect_ratio
resolution
crf
preset
audio_bitrate
volume
position
opacity
fps
width
speed
timestamp
image_duration
frame_rate
font_size
wave_color
Editor task IDs
Use one value below as {task_id}:
| Task ID | Purpose | Files |
|---|---|---|
normalize |
Convert to H.264/AAC MP4 | 1 video |
extract_audio |
Export MP3 audio | 1 video/audio |
resize_916 |
Crop to vertical 9:16 | 1 video |
add_subtitles |
Burn SRT/ASS subtitles | video + subtitle |
burn_lyrics |
Burn styled lyrics | video + subtitle |
text_overlay |
Add caption text | 1 video |
merge_music |
Add background music | video + audio |
thumbnail |
Export JPG frame | 1 video |
watermark |
Overlay logo/image | video + image |
compress |
Reduce video size | 1 video |
batch_compress |
Compress videos into ZIP | 1+ videos |
make_gif |
Create GIF | 1 video |
tiktok_lyrics |
Vertical lyric clip | 1 video |
tiktok_pro_reframer |
Vertical reframe and style | 1 video |
reels_blur_fit |
Blurred 9:16 fit | 1 video |
reels_safe_caption |
Mobile-safe caption | 1 video |
reels_hook_title |
Top hook/title | 1 video |
reels_progress_bar |
Progress bar and trim | 1 video |
reels_loop |
Loop to target duration | 1 video |
reels_subtitle_safe |
Mobile-safe subtitles | video + subtitle |
reels_reaction_stack |
Stack reaction videos | 2 videos |
reels_audio_duck |
Duck music below video | video + audio |
faceless_quote_card |
Text-only quote short | no file |
faceless_story_pages |
Timed text story slides | no file |
faceless_image_narration |
Image with narration | image + audio |
faceless_video_narration |
B-roll with narration | video + audio |
faceless_broll_montage |
Silent b-roll montage | 2+ videos |
series_split_pack |
Split long video into series ZIP | 1 video |
series_episode_badge |
Add episode badge | 1 video |
series_batch_pack |
Package clips as numbered series | 2+ videos |
series_recap_card |
Text-only recap card | no file |
concat |
Join clips | 2+ videos |
slideshow |
Build video from images | 2+ images |
trim |
Cut by start/end | 1 video/audio |
crop_aspect |
Crop to target aspect ratio | 1 video |
waveform |
Create waveform video | 1 audio/video |
extract_frames |
Export frames as ZIP | 1 video |
add_intro_outro |
Join intro/main/outro | 2-3 videos |
speed |
Change playback speed | 1 video |
remove_audio |
Remove video audio | 1 video |
replace_audio |
Replace video audio | video + audio |
JSON Payload Reference
Fields marked * are required.
Rendering
ScenePayload
start*: number >= 0
duration*: number > 0
media*: string path or URL
caption: string
transition: string = "fade"
background: string = "blur"
layout: string = "fill"
effect: string | null
RenderPayload
scenes*: ScenePayload[]
template: string = "tiktok_classic"
preset, creative_style, platform: string | null
output_name: string = "render.mp4"
voiceover, background_music: string | null
music_volume: number = 0.316
music_fade_in, music_fade_out, music_start: number = 0
music_loop, music_ducking: boolean = true
voice_volume: number = 1
subtitle_format: string = "ass"
auto_subtitles: boolean = false
subtitle_language, whisper_model_size: string | null
preview, audio_normalize: boolean = false
watermark, intro, outro: string | null
watermark_position: string = "bottom-right"
callback_url, export_target: string | null
priority: integer = 0
scheduled_at: number | null
normalize: boolean = true
metadata: object = {}
AIReelsPayload
script*: string
voiceover*: string
assets*: string[]
template: string = "tiktok_classic"
creative_style, platform: string | null
output_name: string = "ai_reel.mp4"
background_music: string | null
music_volume: number = 0.316
music_fade_in, music_fade_out, music_start: number = 0
music_loop, music_ducking: boolean = true
voice_volume: number = 1
callback_url, export_target: string | null
BatchPayload
jobs*: RenderPayload[]
ProjectRenderPayload
output_name: string = "project_render.mp4"
template, preset, creative_style, platform: string | null
callback_url, export_target: string | null
preview: boolean = false
normalize: boolean = true
metadata: object = {}
Projects and Editing
ProjectPayload
name*: string
metadata: object = {}
export_settings: object = {}
template: object | null
ProjectSavePayload
project_id: string | null
project*: object
ProjectAssetPayload
project_id*: string
asset*: object
TimelineAddPayload
project_id*: string
track_type: string = "video"
track_id: string | null
item: object = {}
TimelineOperationPayload
project_id*: string
operation: string = "drag"
item_id: string | null
params: object = {}
EffectApplyPayload
project_id, target_id, item_id: string | null
effect*: string
params: object = {}
callback_url: string | null
FilterApplyPayload
project_id, target_id, item_id: string | null
filter*: string
params: object = {}
lut: string | null
callback_url: string | null
TransitionAddPayload
project_id, from_item_id, to_item_id, target_id: string | null
transition*: string
duration: number = 0.45
params: object = {}
callback_url: string | null
KeyframePayload
project_id*: string
target_id*: string
property*: string
time*: number >= 0
value*: any JSON value
easing: string = "linear"
Generation and Platform Tools
GenerationPayload
prompt, text, media, provider: string | null
callback_url, export_target: string | null
params: object = {}
additional JSON fields are accepted
CaptionGeneratePayload
media, audio, text, transcript: string | null
events: object[] | null
template: string = "capcut"
language: string | null
engine: string = "whisper"
word_timestamps: boolean = true
emoji_insertion, speaker_detection: boolean = false
karaoke, animated: boolean = true
callback_url: string | null
additional JSON fields are accepted
AIToolPayload
project_id, media, transcript, text, platform: string | null
callback_url: string | null
params: object = {}
additional JSON fields are accepted
IngestPayload
sources*: [{ "url": string, "type": string|null, "name": string|null }]
callback_url: string | null
AnalyzePayload
media*: string
transcript: string = ""
platform, callback_url: string | null
ClipsPayload
media*: string
clips: object[] | null
callback_url: string | null
ThumbnailPayload
media*: string
text: string = ""
timestamp: number | null
template: string = "bold"
callback_url: string | null
MetadataPayload
topic, transcript: string = ""
platform, callback_url: string | null
PublishPayload
media, asset, title, description: string | null
platforms: string[] = []
platform, scheduled_at: string | null
draft: boolean = true
callback_url: string | null
ToolkitPayload
task*: string
input, media, output_name: string | null
params: object = {}
callback_url, export_target: string | null
additional JSON fields are accepted
Transcription and Subtitles
TranscribePayload
audio*: string path or URL
model_size, language: string | null
task: string = "transcribe"
beam_size: integer = 5
vad_filter, word_timestamps: boolean = true
SubtitlePayload
events*: [{ "start": number, "end": number, "text": string }]
format: string = "srt"
template: string = "tiktok_classic"
SceneBuildPayload
script*: string
assets*: string[]
duration: number | null
transition: string = "fade"
creative_style: string | null
Framework and UI Endpoints
These are not business API operations:
| Path | Purpose |
|---|---|
/dashboard |
Renderer Gradio interface. |
/tts/ |
Kokoro TTS Gradio interface. |
/music/ |
MusicGen Gradio interface. |
/whisper/ |
Whisper Gradio interface. |
/editor/ |
FFmpeg editor Gradio interface. |
/mcp/ |
MCP Streamable HTTP transport; use an MCP client rather than a normal REST request. |
/dashboard/gradio_api/mcp/ |
Gradio-native MCP transport for documented dashboard actions. |
/mcp-health |
MCP transport discovery and custom tool count. |
/docs |
Root FastAPI Swagger UI when ENABLE_API_DOCS=true. |
/redoc |
Root FastAPI ReDoc UI when ENABLE_API_DOCS=true. |
/openapi.json |
Root renderer OpenAPI schema when ENABLE_API_DOCS=true. |
/<service>/docs |
Mounted service Swagger UI when ENABLE_API_DOCS=true. |
/<service>/openapi.json |
Mounted service OpenAPI schema when ENABLE_API_DOCS=true. |