Public API

Quickstart

Create a test key, upload a file, and download a conversion result.

1. Create a test key

In your organization's Settings → API Keys tab, create a key with mode Test and copy its secret. It is shown once. Set it as KEY in the examples below.

export BASE=https://api.convertere.io/v1
export KEY=cvio_test_...

2. Create a job

This task graph imports an upload, converts PNG to WebP, and exports a download URL. The response contains the job id and, on the import-1 task, a presigned uploadUrl (tasks[0].result.uploadUrl).

curl -s -X POST "$BASE/jobs" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
  -d '{"tasks":{"import-1":{"operation":"import/upload"},"convert-1":{"operation":"convert","input":"import-1","input_format":"png","output_format":"webp","options":{}},"export-1":{"operation":"export/url","input":"convert-1"}}}' \
  | tee job.json

JOB_ID=$(jq -r .id job.json)
UPLOAD_URL=$(jq -r '.tasks[0].result.uploadUrl' job.json)
const base = "https://api.convertere.io/v1";
const key = process.env.CONVERTERE_API_KEY; // Node 20+
const response = await fetch(`${base}/jobs`, {
	method: "POST",
	headers: {
		Authorization: `Bearer ${key}`,
		"Content-Type": "application/json",
	},
	body: JSON.stringify({
		tasks: {
			"import-1": { operation: "import/upload" },
			"convert-1": {
				operation: "convert",
				input: "import-1",
				input_format: "png",
				output_format: "webp",
				options: {},
			},
			"export-1": { operation: "export/url", input: "convert-1" },
		},
	}),
});
const job = await response.json();
const uploadUrl = job.tasks[0].result.uploadUrl;
import os
import requests

base = "https://api.convertere.io/v1"
key = os.environ["CONVERTERE_API_KEY"]
response = requests.post(f"{base}/jobs", headers={"Authorization": f"Bearer {key}"}, json={"tasks": {
    "import-1": {"operation": "import/upload"},
    "convert-1": {"operation": "convert", "input": "import-1", "input_format": "png", "output_format": "webp", "options": {}},
    "export-1": {"operation": "export/url", "input": "convert-1"}
}})
job = response.json()
upload_url = job["tasks"][0]["result"]["uploadUrl"]

The response looks like this (shortened):

{
	"id": "11111111-1111-4111-8111-111111111111",
	"status": "waiting",
	"mode": "single",
	"testMode": true,
	"test_mode": true,
	"credits_estimated": 1,
	"tasks": [
		{
			"name": "import-1",
			"operation": "import/upload",
			"status": "waiting",
			"result": {
				"uploadUrl": "https://…",
				"uploadExpiresAt": "2026-10-10T13:00:00.000Z"
			}
		},
		{ "name": "convert-1", "operation": "convert", "status": "waiting" },
		{ "name": "export-1", "operation": "export/url", "status": "waiting" }
	],
	"createdAt": "2026-10-10T12:00:00.000Z",
	"created_at": "2026-10-10T12:00:00.000Z",
	"expires_at": null,
	"api_key_id": "22222222-2222-4222-8222-222222222222"
}

3. Upload the file

Send the file bytes in a single PUT to the uploadUrl. The URL is presigned: do not add the API key header.

curl -X PUT --upload-file sample.png "$UPLOAD_URL"
import { readFile } from "node:fs/promises";
await fetch(uploadUrl, { method: "PUT", body: await readFile("sample.png") });
with open("sample.png", "rb") as file:
    requests.put(upload_url, data=file).raise_for_status()

4. Wait for the job

wait accepts 0–25 seconds. The request returns as soon as the job's status changes, or after the wait with the current state; call it again until the status is finished (or error). Fetching the job also notices your upload and starts the conversion.

curl "$BASE/jobs/$JOB_ID?wait=25" -H "Authorization: Bearer $KEY"
let status;
do {
	status = await fetch(`${base}/jobs/${job.id}?wait=25`, {
		headers: { Authorization: `Bearer ${key}` },
	}).then((r) => r.json());
} while (
	!["finished", "error", "cancelled", "expired"].includes(status.status)
);
while True:
    status = requests.get(f"{base}/jobs/{job['id']}", params={"wait": 25},
                          headers={"Authorization": f"Bearer {key}"}).json()
    if status["status"] in ("finished", "error", "cancelled", "expired"):
        break

5. Download the result

When the job is finished, read the result URL from the export/url task and download it. The link is valid for 24 hours.

curl -L "$(curl -s "$BASE/jobs/$JOB_ID" -H "Authorization: Bearer $KEY" \
  | jq -r '.tasks[] | select(.operation=="export/url") | .result.url')" -o output.webp
import { writeFile } from "node:fs/promises";

const resultUrl = status.tasks.find((t) => t.operation === "export/url").result
	.url;
const file = await fetch(resultUrl);
await writeFile("output.webp", Buffer.from(await file.arrayBuffer()));
result_url = next(t for t in status["tasks"] if t["operation"] == "export/url")["result"]["url"]
with requests.get(result_url, stream=True) as result:
    result.raise_for_status()
    with open("output.webp", "wb") as output:
        for chunk in result.iter_content(8192):
            output.write(chunk)

A test key never converts anything: the "result" is a copy of the file you uploaded. See Test mode. To use real conversions create a Live key; see Credits.

Next steps

  • Skip polling with webhooks.
  • Convert a file from a URL, or upload more than 100 MB, in Uploads.
  • Make job creation safe to retry with an Idempotency-Key.

On this page