Video Conversion API
Convert video between MP4, MOV, AVI, MKV, and WEBM. Video encodes can take minutes, so this is an async, submit-then-poll endpoint rather than one blocking request — same ffmpeg engine behind TransConvert's website converter.
curl -X POST \ .../api/v1/convert-async.php \ -H "Authorization: Bearer ..." \ -F "category=video" \ -F "target=MP4" \ -F "file=@clip.mov" # { "job_id": "job_...", "status": "queued" }
Video and audio conversions can run for minutes, too long to hold open a single synchronous request — these use a submit-then-poll flow instead of the endpoint above. Submit a file, get a job_id back right away, then poll for its status until it's done.
Submit a job
https://transconvert.com/api/v1/convert-async.php
| Field | Description |
|---|---|
Authorization | Required. "Bearer tc_live_...". |
category | Set to "video". |
target | Required. Output format code: "MP4", "MOV", "AVI", "MKV", or "WEBM". |
file | Required. The video file. |
curl -X POST \ https://transconvert.com/api/v1/convert-async.php \ -H "Authorization: Bearer tc_live_your_key_here" \ -F "category=video" \ -F "target=MP4" \ -F "file=@clip.mov" \ -o output.mp4
<?php $ch = curl_init('https://transconvert.com/api/v1/convert-async.php'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer tc_live_your_key_here'], CURLOPT_POSTFIELDS => [ 'category' => 'video', 'target' => 'MP4', 'file' => new CURLFile('clip.mov'), ], ]); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($status === 200) { file_put_contents('output.mp4', $response); } else { $error = json_decode($response, true); echo $error['error']['message']; }
const form = new FormData(); form.append('category', 'video'); form.append('target', 'MP4'); form.append('file', new Blob([fs.readFileSync('clip.mov')]), 'clip.mov'); const res = await fetch('https://transconvert.com/api/v1/convert-async.php', { method: 'POST', headers: { Authorization: 'Bearer tc_live_your_key_here' }, body: form, }); if (res.ok) { fs.writeFileSync('output.mp4', Buffer.from(await res.arrayBuffer())); } else { const { error } = await res.json(); console.error(error.message); }
import requests with open('clip.mov', 'rb') as f: response = requests.post( 'https://transconvert.com/api/v1/convert-async.php', headers={'Authorization': 'Bearer tc_live_your_key_here'}, data={'category': 'video', 'target': 'MP4'}, files={'file': f}, ) if response.status_code == 200: with open('output.mp4', 'wb') as out: out.write(response.content) else: print(response.json()['error']['message'])
# gem install multipart-post require 'net/http' require 'net/http/post/multipart' url = URI('https://transconvert.com/api/v1/convert-async.php') File.open('clip.mov') do |file| req = Net::HTTP::Post::Multipart.new url, 'category' => 'video', 'target' => 'MP4', 'file' => UploadIO.new(file, 'application/octet-stream', 'clip.mov') req['Authorization'] = 'Bearer tc_live_your_key_here' res = Net::HTTP.start(url.host, url.port, use_ssl: true) do |http| http.request(req) end if res.code == '200' File.write('output.mp4', res.body) else puts JSON.parse(res.body)['error']['message'] end end
// Gradle: implementation("com.squareup.okhttp3:okhttp:4.+") OkHttpClient client = new OkHttpClient(); RequestBody body = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("category", "video") .addFormDataPart("target", "MP4") .addFormDataPart("file", "clip.mov", RequestBody.create(new File("clip.mov"), MediaType.parse("application/octet-stream"))) .build(); Request request = new Request.Builder() .url("https://transconvert.com/api/v1/convert-async.php") .header("Authorization", "Bearer tc_live_your_key_here") .post(body) .build(); try (Response response = client.newCall(request).execute()) { if (response.isSuccessful()) { Files.write(Paths.get("output.mp4"), response.body().bytes()); } else { System.err.println(response.body().string()); } }
Poll for status
Poll this every few seconds with the job_id you got back. "status" is one of queued, processing, completed, or failed.
https://transconvert.com/api/v1/job-status.php?job_id=job_...
curl -H "Authorization: Bearer tc_live_your_key_here" \ https://transconvert.com/api/v1/job-status.php?job_id=job_...
Download the result
Once status is "completed", the response includes a download_url — the same status URL with &download=1 appended. Requesting it then streams the converted file's raw bytes, same headers as every other endpoint on this page. The result is deleted the moment it's downloaded, or automatically after a short retention window if it's never downloaded.
scheduleJob results are deleted immediately after download, or automatically after a short retention window if never downloaded — download promptly.
Errors
Every failure returns a JSON error envelope with a "code" your code can branch on, plus a human-readable "message". Some errors include extra fields (quota_exceeded includes "limit" and "used", for example).
| Status & code | When it happens |
|---|---|
401 missing_key | No Authorization header was sent. |
401 invalid_key | The key doesn't exist, or has been revoked. |
403 account_suspended | The account owning this key is suspended. |
403 plan_required | The account is on the Free plan — API access needs Basic, Lite, Pro, or Team. |
400 invalid_category | "category" wasn't "image" or "document". |
400 invalid_target | "target" isn't a supported output format for that category. |
400 no_file | No file was sent, or the upload failed — the field must be named "file". |
413 file_too_large | The file exceeds your plan's max upload size. |
429 quota_exceeded | The plan's monthly conversion-minutes allowance is used up. Resets at the start of the next calendar month. |
429 concurrency_limit | Too many conversions already running at once for this account (shared with the website) — wait for one to finish and retry. |
404 job_not_found | No job with that id exists for this account (also returned for another account's job_id — its existence is never revealed). |
410 result_gone | The job completed, but its result has since been deleted (results are removed immediately after download, or automatically after a short retention window). |
400/415/422/500/503 conversion_failed | The file itself couldn't be converted — "message" explains why. The status code varies with the reason: 400/415/422 mean the file or target won't work no matter how many times you retry; 500/503 mean a server-side problem, and 503 specifically is worth a short retry. |
Supported formats
MP4, MOV, AVI, MKV, WEBM