Developers

Convert files with one API call

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.

  • Base URL https://convertr.org/api/v1
  • 100 free credits per month
  • MCP server at https://convertr.org/mcp
On this page

Quick start

Convert your first file in three steps.

1. Get an API key

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.

Shell
export CONVERTR_API_KEY="cvk_..."

2. Convert a file

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
curl "https://convertr.org/api/v1/conversions?wait=60" \
  -H "Authorization: Bearer $CONVERTR_API_KEY" \
  -F output_format=mp3 \
  -F [email protected]
Python
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())
JavaScript
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());

3. Download the result

A finished conversion has status set to succeeded. Download the file from output.download_url. The link works until output.expires_at.

Response
{
  "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"
}
Download
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.

Authentication

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.

Endpoints

Base URL: https://convertr.org/api/v1. Requests and responses use JSON, except for file uploads, which use multipart/form-data.

MethodPathKeyPurpose
GET/formatsNoList every input format with its output formats.
GET/formats/{input}NoList the output formats of one input format.
POST/conversionsYesStart a conversion from a file or a URL.
GET/conversions/{id}YesRead a conversion. Supports wait.
DELETE/conversions/{id}YesDelete a conversion and its files at once.
GET/accountYesRead your plan, credits and limits.
GET/usageYesList credit charges, refunds and purchases.
GET/openapi.jsonNoOpenAPI 3.1 description of this API.

GET /formats

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
curl "https://convertr.org/api/v1/formats"
Python
import requests

API = "https://convertr.org/api/v1"

response = requests.get(
    f"{API}/formats",
)
response.raise_for_status()
print(response.json())
JavaScript
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());
Response
{
  "data": [
    {
      "input": "mp4",
      "outputs": [
        { "format": "mp3", "group": "Audio" },
        { "format": "wav", "group": "Audio" },
        { "format": "webm", "group": "Video" }
      ]
    }
  ]
}

GET /formats/{input}

Public. Returns the output formats of one input format. An unknown input returns 404 with the error code not_found.

curl
curl "https://convertr.org/api/v1/formats/mp4"
Python
import requests

API = "https://convertr.org/api/v1"

response = requests.get(
    f"{API}/formats/mp4",
)
response.raise_for_status()
print(response.json())
JavaScript
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());
Response
{
  "input": "mp4",
  "outputs": [
    { "format": "mp3", "group": "Audio" },
    { "format": "wav", "group": "Audio" },
    { "format": "webm", "group": "Video" }
  ]
}

POST /conversions

Starts a conversion. Send a file as multipart/form-data, or send a URL as JSON. Both return a conversion object.

FieldTypeDescription
filefileMultipart only. The file to convert. Required.
urlstringJSON only. A public URL of the file. Convertr downloads it. Required.
output_formatstringThe format to convert to, such as mp3. Required.
input_formatstringThe format of the input. Optional. The default is the file extension.
filenamestringJSON only. Name of the file, for example x.mp4. Optional.
settingsobjectConversion 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
curl "https://convertr.org/api/v1/conversions?wait=60" \
  -H "Authorization: Bearer $CONVERTR_API_KEY" \
  -F output_format=mp3 \
  -F [email protected]
Python
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())
JavaScript
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
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"}'
Python
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())
JavaScript
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):

Response
{
  "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
}

GET /conversions/{id}

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
curl "https://convertr.org/api/v1/conversions/$CONVERSION_ID?wait=30" \
  -H "Authorization: Bearer $CONVERTR_API_KEY"
Python
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())
JavaScript
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());

DELETE /conversions/{id}

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
curl -X DELETE "https://convertr.org/api/v1/conversions/$CONVERSION_ID" \
  -H "Authorization: Bearer $CONVERTR_API_KEY"
Python
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)
JavaScript
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);

GET /account

Returns your plan, free credits, paid credit lots and the largest file you can send. plan is free, paid or unmetered.

curl
curl "https://convertr.org/api/v1/account" \
  -H "Authorization: Bearer $CONVERTR_API_KEY"
Python
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())
JavaScript
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());
Response
{
  "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 }
}

GET /usage

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
curl "https://convertr.org/api/v1/usage?limit=50" \
  -H "Authorization: Bearer $CONVERTR_API_KEY"
Python
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())
JavaScript
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());
Response
{
  "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
}

GET /openapi.json

Public. The OpenAPI 3.1 file describes every endpoint. Use it to generate a client or to load the API into a tool.

Conversion object

Every conversion endpoint returns this object.

FieldDescription
idThe conversion id. Use it to read or delete the conversion.
statusqueued, processing, succeeded or failed.
progressProgress from 0 to 100.
inputfilename, format and size_bytes of the input.
outputfilename, format, size_bytes, download_url and expires_at. It is null until the job succeeds.
credits_chargedCredits used for this conversion.
errorcode and message when the job failed. Otherwise null.
created_at, finished_atTimestamps in UTC. finished_at is null while the job runs.

Errors

Errors return JSON and a matching HTTP status.

Error response
{
  "error": {
    "code": "insufficient_credits",
    "message": "Your account has no credits left. Buy credits or wait for the monthly free credits."
  }
}
HTTPCodeMeaning
401invalid_api_keyThe key is missing, wrong or revoked.
402insufficient_creditsYou have no credits left. Buy credits or wait for the monthly free credits.
403email_not_verifiedVerify your email address first.
404not_foundThe conversion or the format does not exist.
413file_too_largeThe input is larger than your plan allows.
415unsupported_conversionConvertr cannot convert this input format to this output format.
422validation_failedA field is missing or has a wrong value.
429rate_limitedToo many requests. Wait for the number of seconds in the Retry-After header.
503no_worker_availableNo conversion worker is free. Try again in a moment.
500internal_errorSomething 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.

Credits and limits

  • Credits: one credit pays for one conversion of an input up to 100 MB. Each further started 100 MB costs one more credit.
  • Free plan: 100 credits per calendar month (UTC). It needs a verified email. The largest input is 100 MB.
  • Paid credits: one-time packs, valid for 12 months. Convertr uses them after the monthly free credits. The largest input is 1 GB. Send files over 100 MB as a 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.
  • Refunds: failed conversions are refunded automatically.
  • Rate limits per key: 60 conversion starts per minute and 600 other requests per minute. A limited request returns 429 and a Retry-After header.
  • Storage: Convertr deletes files 24 hours after the conversion, or at once when you call DELETE.

See Pricing for the credit packs.

MCP server

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 Code

Shell
claude mcp add --transport http convertr https://convertr.org/mcp --header "X-API-Key: cvk_..."

Claude Desktop and Cursor

Add this to the MCP settings file of the app:

JSON
{
  "mcpServers": {
    "convertr": {
      "url": "https://convertr.org/mcp",
      "headers": { "X-API-Key": "cvk_..." }
    }
  }
}

VS Code

Add this to .vscode/mcp.json:

JSON
{
  "servers": {
    "convertr": {
      "type": "http",
      "url": "https://convertr.org/mcp",
      "headers": { "X-API-Key": "cvk_..." }
    }
  }
}

Tools

ToolWhat it does
list_formatsLists the supported input and output formats.
convert_fileStarts a conversion and returns the conversion.
get_conversionReads the state and the download link of a conversion.
delete_conversionDeletes a conversion and its files.
get_accountShows your plan, credits and limits.

For AI agents and tools

These files describe Convertr in a form that tools read well: