Developers
Send a file or a URL. Get the converted file back. Use the REST API from any language, or add the MCP server to your AI assistant.
https://convertr.org/api/v1https://convertr.org/mcpConvert your first file in three steps.
Create an account, verify your email, then open API keys and create a key. A key starts with cvk_. Convertr shows it once, so copy it right away. The free plan gives you 100 credits every month.
export CONVERTR_API_KEY="cvk_..."Upload a file and ask for an output format. The wait parameter holds the request open until the job ends, up to 90 seconds.
curl "https://convertr.org/api/v1/conversions?wait=60" \
-H "Authorization: Bearer $CONVERTR_API_KEY" \
-F output_format=mp3 \
-F [email protected]import os
import requests
API = "https://convertr.org/api/v1"
headers = {"Authorization": f"Bearer {os.environ['CONVERTR_API_KEY']}"}
with open("clip.mp4", "rb") as source:
response = requests.post(
f"{API}/conversions",
headers=headers,
params={"wait": 60},
data={"output_format": "mp3"},
files={"file": source},
)
response.raise_for_status()
print(response.json())import { openAsBlob } from "node:fs";
const API = "https://convertr.org/api/v1";
const headers = { Authorization: `Bearer ${process.env.CONVERTR_API_KEY}` };
const form = new FormData();
form.append("output_format", "mp3");
form.append("file", await openAsBlob("clip.mp4"), "clip.mp4");
const response = await fetch(`${API}/conversions?wait=60`, {
method: "POST",
body: form,
headers,
});
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());A finished conversion has status set to succeeded. Download the file from output.download_url. The link works until output.expires_at.
{
"id": "9f1c2e7a-5b3d-4c8e-a1f0-6d2b7c9e4a31",
"status": "succeeded",
"progress": 100,
"input": { "filename": "clip.mp4", "format": "mp4", "size_bytes": 4821337 },
"output": {
"filename": "clip.mp3",
"format": "mp3",
"size_bytes": 612044,
"download_url": "https://gw1.convertr.org/api/download/...",
"expires_at": "2026-10-31T10:15:04Z"
},
"credits_charged": 1,
"error": null,
"created_at": "2026-10-30T10:15:00Z",
"finished_at": "2026-10-30T10:15:04Z"
}curl -L -o clip.mp3 "https://gw1.convertr.org/api/download/..."If the job needs longer than wait, the response has status set to queued or processing. Poll GET /conversions/{id} until it ends.
Send your API key with every request, except for the two public format endpoints. Use one of these headers:
Authorization: Bearer cvk_...X-API-Key: cvk_...Create and revoke keys on the API keys page. You need a verified email address. Keep keys on your server. Do not put them in browser code or in public repositories.
A missing or wrong key returns 401 with the error code invalid_api_key.
Base URL: https://convertr.org/api/v1. Requests and responses use JSON, except for file uploads, which use multipart/form-data.
| Method | Path | Key | Purpose |
|---|---|---|---|
| GET | /formats | No | List every input format with its output formats. |
| GET | /formats/{input} | No | List the output formats of one input format. |
| POST | /conversions | Yes | Start a conversion from a file or a URL. |
| GET | /conversions/{id} | Yes | Read a conversion. Supports wait. |
| DELETE | /conversions/{id} | Yes | Delete a conversion and its files at once. |
| GET | /account | Yes | Read your plan, credits and limits. |
| GET | /usage | Yes | List credit charges, refunds and purchases. |
| GET | /openapi.json | No | OpenAPI 3.1 description of this API. |
Public. Returns every input format with the output formats it can convert to. The group tells you the kind of output, such as Audio or Video.
curl "https://convertr.org/api/v1/formats"import requests
API = "https://convertr.org/api/v1"
response = requests.get(
f"{API}/formats",
)
response.raise_for_status()
print(response.json())const API = "https://convertr.org/api/v1";
const response = await fetch(`${API}/formats`);
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());{
"data": [
{
"input": "mp4",
"outputs": [
{ "format": "mp3", "group": "Audio" },
{ "format": "wav", "group": "Audio" },
{ "format": "webm", "group": "Video" }
]
}
]
}Public. Returns the output formats of one input format. An unknown input returns 404 with the error code not_found.
curl "https://convertr.org/api/v1/formats/mp4"import requests
API = "https://convertr.org/api/v1"
response = requests.get(
f"{API}/formats/mp4",
)
response.raise_for_status()
print(response.json())const API = "https://convertr.org/api/v1";
const response = await fetch(`${API}/formats/mp4`);
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());{
"input": "mp4",
"outputs": [
{ "format": "mp3", "group": "Audio" },
{ "format": "wav", "group": "Audio" },
{ "format": "webm", "group": "Video" }
]
}Starts a conversion. Send a file as multipart/form-data, or send a URL as JSON. Both return a conversion object.
| Field | Type | Description |
|---|---|---|
file | file | Multipart only. The file to convert. Required. |
url | string | JSON only. A public URL of the file. Convertr downloads it. Required. |
output_format | string | The format to convert to, such as mp3. Required. |
input_format | string | The format of the input. Optional. The default is the file extension. |
filename | string | JSON only. Name of the file, for example x.mp4. Optional. |
settings | object | Conversion settings. Optional. In multipart requests, send it as a JSON string. |
In a multipart request, send output_format and input_format before the file part. You can also pass them as query parameters. curl -F keeps the order you write.
Add ?wait=N (0 to 90 seconds) to hold the request until the job ends or N seconds pass. The response is 201 for a job that is still running. It is 200 when the job ended in the time you allowed, with status set to succeeded or failed.
Upload a file:
curl "https://convertr.org/api/v1/conversions?wait=60" \
-H "Authorization: Bearer $CONVERTR_API_KEY" \
-F output_format=mp3 \
-F [email protected]import os
import requests
API = "https://convertr.org/api/v1"
headers = {"Authorization": f"Bearer {os.environ['CONVERTR_API_KEY']}"}
with open("clip.mp4", "rb") as source:
response = requests.post(
f"{API}/conversions",
headers=headers,
params={"wait": 60},
data={"output_format": "mp3"},
files={"file": source},
)
response.raise_for_status()
print(response.json())import { openAsBlob } from "node:fs";
const API = "https://convertr.org/api/v1";
const headers = { Authorization: `Bearer ${process.env.CONVERTR_API_KEY}` };
const form = new FormData();
form.append("output_format", "mp3");
form.append("file", await openAsBlob("clip.mp4"), "clip.mp4");
const response = await fetch(`${API}/conversions?wait=60`, {
method: "POST",
body: form,
headers,
});
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());Convert from a URL:
curl "https://convertr.org/api/v1/conversions?wait=60" \
-H "Authorization: Bearer $CONVERTR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/clip.mp4", "output_format": "mp3"}'import os
import requests
API = "https://convertr.org/api/v1"
headers = {"Authorization": f"Bearer {os.environ['CONVERTR_API_KEY']}"}
response = requests.post(
f"{API}/conversions",
headers=headers,
params={"wait": 60},
json={"url": "https://example.com/clip.mp4", "output_format": "mp3"},
)
response.raise_for_status()
print(response.json())const API = "https://convertr.org/api/v1";
const headers = { Authorization: `Bearer ${process.env.CONVERTR_API_KEY}` };
const response = await fetch(`${API}/conversions?wait=60`, {
method: "POST",
body: JSON.stringify({"url": "https://example.com/clip.mp4", "output_format": "mp3"}),
headers: { ...headers, "Content-Type": "application/json" },
});
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());Response without wait (201):
{
"id": "9f1c2e7a-5b3d-4c8e-a1f0-6d2b7c9e4a31",
"status": "queued",
"progress": 0,
"input": { "filename": "clip.mp4", "format": "mp4", "size_bytes": 4821337 },
"output": null,
"credits_charged": 1,
"error": null,
"created_at": "2026-10-30T10:15:00Z",
"finished_at": null
}Returns the current state of a conversion. It supports ?wait=N as well, so you can poll with a long request instead of a short loop. An unknown id returns 404.
curl "https://convertr.org/api/v1/conversions/$CONVERSION_ID?wait=30" \
-H "Authorization: Bearer $CONVERTR_API_KEY"import os
import requests
API = "https://convertr.org/api/v1"
headers = {"Authorization": f"Bearer {os.environ['CONVERTR_API_KEY']}"}
conversion_id = "9f1c2e7a-5b3d-4c8e-a1f0-6d2b7c9e4a31"
response = requests.get(
f"{API}/conversions/{conversion_id}",
headers=headers,
params={"wait": 30},
)
response.raise_for_status()
print(response.json())const API = "https://convertr.org/api/v1";
const headers = { Authorization: `Bearer ${process.env.CONVERTR_API_KEY}` };
const conversionId = "9f1c2e7a-5b3d-4c8e-a1f0-6d2b7c9e4a31";
const response = await fetch(`${API}/conversions/${conversionId}?wait=30`, {
headers,
});
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());Deletes the input and output files of a conversion at once. Returns 204 with no body. Without a delete, Convertr removes files after 24 hours.
curl -X DELETE "https://convertr.org/api/v1/conversions/$CONVERSION_ID" \
-H "Authorization: Bearer $CONVERTR_API_KEY"import os
import requests
API = "https://convertr.org/api/v1"
headers = {"Authorization": f"Bearer {os.environ['CONVERTR_API_KEY']}"}
conversion_id = "9f1c2e7a-5b3d-4c8e-a1f0-6d2b7c9e4a31"
response = requests.delete(
f"{API}/conversions/{conversion_id}",
headers=headers,
)
response.raise_for_status()
print(response.status_code)const API = "https://convertr.org/api/v1";
const headers = { Authorization: `Bearer ${process.env.CONVERTR_API_KEY}` };
const conversionId = "9f1c2e7a-5b3d-4c8e-a1f0-6d2b7c9e4a31";
const response = await fetch(`${API}/conversions/${conversionId}`, {
method: "DELETE",
headers,
});
if (!response.ok) throw new Error(await response.text());
console.log(response.status);Returns your plan, free credits, paid credit lots and the largest file you can send. plan is free, paid or unmetered.
curl "https://convertr.org/api/v1/account" \
-H "Authorization: Bearer $CONVERTR_API_KEY"import os
import requests
API = "https://convertr.org/api/v1"
headers = {"Authorization": f"Bearer {os.environ['CONVERTR_API_KEY']}"}
response = requests.get(
f"{API}/account",
headers=headers,
)
response.raise_for_status()
print(response.json())const API = "https://convertr.org/api/v1";
const headers = { Authorization: `Bearer ${process.env.CONVERTR_API_KEY}` };
const response = await fetch(`${API}/account`, {
headers,
});
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());{
"user": { "id": 42, "name": "Ada", "email": "[email protected]" },
"plan": "paid",
"free": { "monthly": 100, "used": 12, "remaining": 88, "resets_at": "2026-11-01T00:00:00Z" },
"credits": {
"balance": 3500,
"lots": [
{ "id": 7, "credits": 4000, "remaining": 3500, "expires_at": "2027-10-12T09:30:00Z", "source": "purchase" }
]
},
"limits": { "max_file_bytes": 1073741824 }
}Lists credit movements, newest first. kind is charge, refund, grant, purchase or expire. Use limit and the next_cursor of the last page as cursor to read more.
curl "https://convertr.org/api/v1/usage?limit=50" \
-H "Authorization: Bearer $CONVERTR_API_KEY"import os
import requests
API = "https://convertr.org/api/v1"
headers = {"Authorization": f"Bearer {os.environ['CONVERTR_API_KEY']}"}
response = requests.get(
f"{API}/usage",
headers=headers,
params={"limit": 50},
)
response.raise_for_status()
print(response.json())const API = "https://convertr.org/api/v1";
const headers = { Authorization: `Bearer ${process.env.CONVERTR_API_KEY}` };
const response = await fetch(`${API}/usage?limit=50`, {
headers,
});
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());{
"data": [
{ "id": 311, "kind": "charge", "credits": -1, "conversion_id": "9f1c2e7a-5b3d-4c8e-a1f0-6d2b7c9e4a31", "created_at": "2026-10-30T10:15:00Z" },
{ "id": 310, "kind": "purchase", "credits": 4000, "conversion_id": null, "created_at": "2026-10-12T09:30:00Z" }
],
"next_cursor": null
}Public. The OpenAPI 3.1 file describes every endpoint. Use it to generate a client or to load the API into a tool.
Every conversion endpoint returns this object.
| Field | Description |
|---|---|
id | The conversion id. Use it to read or delete the conversion. |
status | queued, processing, succeeded or failed. |
progress | Progress from 0 to 100. |
input | filename, format and size_bytes of the input. |
output | filename, format, size_bytes, download_url and expires_at. It is null until the job succeeds. |
credits_charged | Credits used for this conversion. |
error | code and message when the job failed. Otherwise null. |
created_at, finished_at | Timestamps in UTC. finished_at is null while the job runs. |
Errors return JSON and a matching HTTP status.
{
"error": {
"code": "insufficient_credits",
"message": "Your account has no credits left. Buy credits or wait for the monthly free credits."
}
}| HTTP | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | The key is missing, wrong or revoked. |
| 402 | insufficient_credits | You have no credits left. Buy credits or wait for the monthly free credits. |
| 403 | email_not_verified | Verify your email address first. |
| 404 | not_found | The conversion or the format does not exist. |
| 413 | file_too_large | The input is larger than your plan allows. |
| 415 | unsupported_conversion | Convertr cannot convert this input format to this output format. |
| 422 | validation_failed | A field is missing or has a wrong value. |
| 429 | rate_limited | Too many requests. Wait for the number of seconds in the Retry-After header. |
| 503 | no_worker_available | No conversion worker is free. Try again in a moment. |
| 500 | internal_error | Something went wrong on our side. Try again. |
A conversion that starts and then fails ends with status set to failed and an error object. Convertr refunds the credits of a failed conversion automatically.
url, because uploads in the request body stop at 100 MB. The server behind a url must deliver the file within 75 seconds, on port 80 or 443.429 and a Retry-After header.DELETE.See Pricing for the credit packs.
The MCP server lets AI agents and coding assistants convert files with the same API key, the same credits and the same limits. Add it to your client:
Endpoint: https://convertr.org/mcp. Send your key in the X-API-Key header.
claude mcp add --transport http convertr https://convertr.org/mcp --header "X-API-Key: cvk_..."Add this to the MCP settings file of the app:
{
"mcpServers": {
"convertr": {
"url": "https://convertr.org/mcp",
"headers": { "X-API-Key": "cvk_..." }
}
}
}Add this to .vscode/mcp.json:
{
"servers": {
"convertr": {
"type": "http",
"url": "https://convertr.org/mcp",
"headers": { "X-API-Key": "cvk_..." }
}
}
}| Tool | What it does |
|---|---|
list_formats | Lists the supported input and output formats. |
convert_file | Starts a conversion and returns the conversion. |
get_conversion | Reads the state and the download link of a conversion. |
delete_conversion | Deletes a conversion and its files. |
get_account | Shows your plan, credits and limits. |
These files describe Convertr in a form that tools read well: