Merge videos
Stitching several clips into a single file usually means opening an editor just to drag pieces onto a timeline in order. This endpoint does the same job through one API call: send the clips in sequence, get back one continuous file, no timeline required.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
Who needs videos merged, and why
Anyone assembling a final video from separate pieces, intro plus main content plus outro, multiple camera angles recorded as separate files, or daily clips that need to become a weekly compilation, runs into the same repetitive task. The merge videos api endpoint takes that assembly step out of a manual editor and turns it into something a script can trigger the moment all the source clips exist, whether that's ten times a day or once a month.
How the concatenation works
POST /video/merge accepts an ordered list of video sources and joins them into a single output file in the exact sequence provided; the order in your request array is the order in the final video, so building a multi-clip video is a matter of arranging links correctly before you send the request, no manual timeline scrubbing involved.
What to expect from the response
Submitting the merge returns a task_id right away while the concatenation happens in the background; the merged file is delivered as a signed webhook call once it's ready, or via a signed link you can fetch yourself within a 24-hour window, whichever fits better into how your system checks for finished work.
A note on why merging isn't always trivial
Two clips that look compatible on screen can still differ in resolution, frame rate, or codec under the hood, and joining them without handling those differences produces a file that stutters or fails to play correctly in some players; a proper merge step normalizes what needs normalizing so the final file behaves as one continuous video rather than a fragile splice of mismatched parts glued together at the seams.
Where merging fits into automation
Because it's asynchronous and billed only when it succeeds, this endpoint slots naturally into pipelines that assemble video from parts on a schedule: a daily recap show built from separate segment files, a course video stitched from individually recorded lessons, or a highlight reel assembled from clips an earlier automated step already picked out for you.
What you can do with it
Intro, content and outro assembly
A creator maintains a fixed intro and outro clip and merges them with a new main video automatically every time a fresh episode is uploaded.
Multi-segment course videos
An online course platform merges individually recorded lesson segments into one continuous module video before publishing it to students.
Daily-to-weekly compilations
A media team automatically merges each day's short clips into a single weekly recap video every Sunday without manual editing.
Multi-camera event footage
An event production workflow merges sequential camera-angle clips recorded separately during a live stream into one continuous archive file.
FAQ
How do I merge multiple videos with the API?
Send a POST request to /video/merge with an ordered list of video sources; you get a task_id immediately and the merged file later via webhook or signed link.
Does the order of clips in my request matter?
Yes, the clips are joined in exactly the order you list them, so arranging your source array correctly determines the final video's sequence.
Can I merge videos with different resolutions or codecs?
Yes, the endpoint normalizes the differences needed to produce one continuous, correctly playing output file rather than requiring identical source formats.
Is merging videos free to test?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
What does the merge endpoint cost?
It's $0.077 per request plus $0.0045 per minute of merged video, with no invented credit system, just a published base plus per-unit rate.
How many clips can I merge in one request?
You can pass as many source clips as your workflow requires in the ordered list; each request is billed on the total minutes of the merged output.
What happens if a merge job fails?
It's retried automatically up to three times, and a job that ultimately fails is never billed, returning a clear error instead.
Is the merge endpoint live yet?
It's in final deployment and not yet accepting jobs; it will be available very soon under the endpoint and pricing described here.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/video/merge \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"audio":"https://ejemplo.com/audio.mp3"}'const res = await fetch("https://api.kit.forhosting.com/video/merge", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"audio": "https://ejemplo.com/audio.mp3"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/video/merge",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"audio": "https://ejemplo.com/audio.mp3"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/video/merge", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"audio":"https://ejemplo.com/audio.mp3"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"audio":"https://ejemplo.com/audio.mp3"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/video/merge", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"audio": "https://ejemplo.com/audio.mp3"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "video.merge",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 500 |
max_minutes | 60 |
max_megapixels | 3.9 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |